Objective-c disable function with conditional macros - objective-c

I have a custom logging function that i would like to disable for realease builds. But the problem is it only lets me to replace that function with another empty one. Here's what i would like to do:
#ifdef SMTH
#define logfunction(...)
#else
void logfunction(NSString *fmt, ...) { some logging code goes here }
#endif
To make this work, i could replace the function with a macro, including VA_ARGS and such, but ... the problem is that my xCode loses code completion inside the braces of logfunction(). Now if the logging facility is defined as a function - code completion works fine.
The only solution i have so far is this:
#ifdef SMTH
void logfunction(NSString *fmt, ...) { /* no code here */ }
#else
void logfunction(NSString *fmt, ...) { some logging code goes here }
#endif
This works fine, but there is a call to an empty function in release builds. Is there any way to work around this?
UPDATE - my bad - everything works
The first example actually works, i simply forgot to do the same conditional macro in the ".h" file ...

I think that your current solution is already good enough. The empty function wont cause much trouble (in terms of wasting much time when it is called). Probably the compiler will even remove the call to the empty function altogether.
However, if you still want to get rid of it, you can try what I am doing:
Wrap your log function into a macro, and define that macro conditionally.
Example:
#ifdef SMTH
#define logfunction(fmt, ...)
#else
#define logfunction(fmt, ...) __logfunction((fmt), ##__VA_ARGS__)
#endif
where __logfunction(NSString *fmt, ...) is your actual logging function. This will completely remove the call to the function, when your SMTH is set.
By the way, you may want to use the DEBUG flag, that is set per default in XCode for non-release builds (see the "Preprocessor Macros" setting in your target in XCode). You would need to switch the cases around inside the #ifdef, obviously, or make it a #ifndef DEBUG.

Related

Visual Objects - Retrieving string DEFINE dynamically - #ifdef is returning false

This is regarding the Visual Objects programming language based upon Clipper.
I'm trying to load the values of a few DEFINE constants, I've tried using #ifdef to determine if they exist however it doesn't seem to work with strings, just numbers or logics, e.g.:
DEFINE TEST_LOGIC := True
DEFINE TEST_NUM := 1
DEFINE TEST_STRING := "HELLO"
#IFDEF TEST_LOGIC
// Runs
#ENDIF
#IFDEF TEST_NUM
// Runs
#ENDIF
#IFDEF TEST_STRING
// Does not run
#ENDIF
Is there some other way of determining whether they exist and returning their values? I've tried VarGet() and MemVarGet() but they can't see the constant and cause a runtime error, and #ifdef cannot accept a method call like !Empty(TEST_STRING) (will not compile), using a direct comparison like #ifdef TEST_STRING > " " also doesn't work (compiles and runs but the code block does not execute).
There doesn't seem to be a way to do this using DEFINE statements containing strings, however if it's changed to a GLOBAL declaration then the #ifdef statement will work as expected.

Check whether function called through function-pointer has a return statement

We have a plugin system that calls functions in dlls (user-generated plugins) by dlopening/LoadLibrarying the dll/so/dylib and then dlsyming/GetProcAddressing the function, and then storing that result in a function pointer.
Unfortunately, due to some bad example code being copy-pasted, some of these dlls in the wild do not have the correct function signature, and do not contain a return statement.
A dll might contain this:
extern "C" void Foo() { stuffWithNoReturn(); } // copy-paste from bad code
or it might contain this:
extern "C" int Foo() { doStuff(); return 1; } // good code
The application that loads the dll relies on the return value, but there are a nontrivial number of dlls out there that don't have the return statement. I am trying to detect this situation, and warn the user about the problem with his plugin.
This naive code should explain what I'm trying to do:
typedef int (*Foo_f)(void);
Foo_f func = (Foo_f)getFromDll(); // does dlsym or GetProcAddress depending on platform
int canary = 0x42424242;
canary = (*func)();
if (canary == 0x42424242)
printf("You idiot, this is the wrong signature!!!\n");
else
real_return_value = canary;
This unfortunately does not work, canary contains a random value after calling a dll that has the known defect. I naively assumed calling a function with no return statement would leave the canary intact, but it doesn't.
My next idea was to write a little bit of inline assembler to call the function, and check the eax register upon return, but Visual Studio 2015 doesn't allow __asm() in x64 code anymore.
I know there is no standards-conform solution to this, as casting the function pointer to the wrong type is of course undefined behavior. But if someone has a solution that works at least on 64bit Windows with Visual C++, or a solution that works with clang on MacOS, I would be most delighted.
#Lorinczy Zsigmond is right in that the contents of the register are undefined if the function does something but returns nothing.
We found however that in practice, the plugins that return nothing also have almost always empty functions that compile to a retn 0x0 and leaves the return register untouched. We can detect this case by spraying the rax register with a known value (0xdeadbeef) and checking for that.

Objective-C macro in preprocessor IF

I have a project with some macros that are defined using Objective-C statements, like this:
#define TEST [someObject someNumber] == 500
I need to define another value based on this result, like this:
#if TEST
#define THING = 1
#else
#define THING = 2
#endif
But, this doesn't work. And I can't use #ifdef TEST because the value is always defined. Even if it's false, it's still defined.
TEST is based on an ObjC statement, and it seems like the preprocessor has no way of evaluating it. So, is there no way to test for this?
In the comments you wrote:
Since TEST must be evaluated during runtime, there's no way to know the value of it during build time. Because the preprocessor can't know the value, it can't test it. Is this correct?
Yes.
The preprocessor runs (at least logically) before the rest of the compiler. It is essentially language and syntax agnostic, and does not even have access to constants defined in your code. The conditional constructs operate solely with preprocessor tokens.

Two different CMake difinitions

With CMake when some definitions are defined they are defined in this way:
add_definitions(-DMY_DEFINITION)
Sometimes I see people make the definitions in a different way:
add_definitions(-DMY_DEFINITION=1)
Then my question is what's the difference between them in the generated C++ project. Thanks.
This is not really related to CMake but more to the C/++ compiler.
In the code the difference is the same between :
#define MY_DEFINITION
and
#define MY_DEFINITION 1
Actually there's not need to define a value for a C/++ macro if the only thing you want is to know if the macro exists (has been defined), like a "flag". Best example is the header include guards :
#ifndef MYHEADER
#define MYHEADER
// ...
#endif
But sometimes people prefer setting a value (like =1) even if they don't need it, because it's more exhaustive, or clear.
More generally speaking when you affect a value to a macro it is because you expect the macro name to be expanded to the value. When not you just expect the value to exist. The way tests are done may be different :
With -DMY_DEFINITION:
#ifdef MY_DEFINITION
// Do something
#else
// Do somthing else
#endif
With -DMY_DEFINITION=1
#if MY_DEFINITION
// Do something
#else
// Do somthing else
#endif

Pre-compile expandable macro

I'm trying to save some time / make my code readable. I have a lot of 'isXXX' messages that return BOOL. I am constantly adding more 'is' messages. Is it possible to make a macro that's expandable at pre-compile time via a list.
I want to specify:
isMacro(1, 2, 3).
And for each of those, I want the macro to expand it into a full -(BOOL)is1 {...}, -(BOOL)is2...
It seems like this would be a good use of the precompiler macro expansion, but I'm not sure how to implement the isMacro(...) part. (Specifically, the ... that expands into full functions before compile).
--- Update:
The 'is' methods are all dynamically computed, but they are all common.
I'm testing a single variable against an enum value and determining whether it's equal. I can't #synthesize them, because it's dynamic. I have all of them in a #property for convenience. I just want something that's like #synthesize, where I can list all of them, and create a dynamic response for each isXXX method.
Also, I don't want to run isCheck:(opMode)mode, since there is no pre-compile checking to make sure it's a valid enum value.
All of the is functions are in the following format:
-(BOOL) isTurtle { return operationMode == Turtle; } The key is that I want it to function as a property for simplicity. Therefore, I don't want something like is:(opMode)mode, where I have to specify BOOL res = [obj is:Tutle];
If you could use Boost.Preprocessor, the BOOST_PP_REPEAT_FROM_TO macro should suit your need.
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#define IS_METHODS(depth, n, aux) -(BOOL)is ## n { return aux == n; }
#implementation Foo
BOOST_PP_REPEAT_FROM_TO(1, 31, IS_METHODS, operationMode)
#end
If you can't, you're out of luck. Implementing BOOST_PP_REPEAT_FROM_TO is about the same effort as just writing the 30+ functions directly.
Also I don't see how [obj isMode:12] is really worse than obj.is12. The former also allows a variable mode, and is less cryptic to other programmers (think about the maintenance effort).