Heads up: This is a weird question.
I've got some really useful macros that I like to use to simplify some logging. For example I can do Log(@"My message with arguments: %@, %@, %@", @"arg1", @"arg2", @"arg3")
, and that will get expanded into a more complex method invocation that includes things like self
, _cmd
, __FILE__
, __LINE__
, etc, so that I can easily track where things are getting logged. This works great.
Now I'd like to expand my macros to not only work with Objective-C methods, but general C functions. The problem is the self
and _cmd
portions that are in the macro expansion. These two parameters don't exist in C functions. Ideally, I'd like to be able to use this same set of macros within C functions, but I'm running into problems. When I use (for example) my Log()
macro, I get compiler warnings about self
and _cmd
being undeclared (which makes total sense).
My first thought was to do something like the following (in my macro):
if (thisFunctionIsACFunction) {
DoLogging(nil, nil, format, ##__VA_ARGS__);
} else {
DoLogging(self, _cmd, format, ##__VA_ARGS__);
}
This still produces compiler warnings, since the entire if() statement is substituted in place of the macro, resulting in errors with the self
and _cmd
keywords (even though they will never be executed during function execution).
My next thought was to do something like this (in my macro):
if (thisFunctionIsACFunction) {
#define SELF nil
#define CMD nil
} else {
#define SELF self
#define CMD _cmd
}
DoLogging(SELF, CMD, format, ##__VA_ARGS__);
That doesn't work, unfortunately. I get "error: '#' is not followed by a macro parameter" on my first #define
.
My other thought was to create a second set of macros, specifically for use in C functions. This reeks of a bad code smell, and I really don't want to do this.
Is there some way I can use the same set of macros from within both Objective-C methods and C functions, and only reference self
and _cmd
if the macro is in an Objective-C method?
edit more information:
thisFunctionIsACFunction
is determined in a pretty rudimentary way (and I'm definitely open to improvements and suggestions). Basically it's this:
BOOL thisFunctionIsACFunction == (__PRETTY_FUNCTION__[0] != '-' && __PRETTY_FUNCTION__[0] != '+');
It's relying on the behavior of the compiler to prepend a '-' or '+' for instance and class methods on Objective-C objects. Anything else must be a C function (since C functions can't have names that begin with '-' or '+').
I understand that this check is technically a runtime check, since __PRETTY_FUNCTION__
gets replaced with a char*
, and this is probably the major roadblock to my request for help.