条件宏扩展 [英] Conditional macro expansion

查看:82
本文介绍了条件宏扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:这是一个奇怪的问题.

Heads up: This is a weird question.

我有一些非常有用的宏,可以用来简化某些日志记录.例如,我可以执行Log(@"My message with arguments: %@, %@, %@", @"arg1", @"arg2", @"arg3"),它将扩展为更复杂的方法调用,其中包括self_cmd__FILE____LINE__等内容,因此我可以轻松地跟踪内容正在记录.效果很好.

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.

现在,我想扩展宏,使其不仅可以与Objective-C方法一起使用,而且还可以与常规C函数一起使用.问题是宏扩展中的self_cmd部分.这两个参数不C函数存在.理想情况下,我想能够使用同组的C函数的宏,但我遇到了问题.当我使用(例如)我的Log()宏时,我得到有关未声明self_cmd的编译器警告(这很有意义).

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__);
}

这仍然会产生编译器警告,因为将整个if()语句替换为宏,从而导致self_cmd关键字出现错误(即使它们永远不会在函数执行期间执行).

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__);

这是不行的,很遗憾.我得到错误:‘#’后面没有宏参数".我第一次<12>

That doesn't work, unfortunately. I get "error: '#' is not followed by a macro parameter" on my first #define.

我的另一个想法是创建第二组宏,专门用于C函数.这有点难闻的代码气味,我真的不想这样做.

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.

有一些方法我可以使用相同的一组宏从目标C的方法和C函数两者内,并且只能引用如果宏是在一个Objective-C的方法?

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?

修改更多信息:

在一个非常简陋的方式确定(我肯定愿意将改进建议).基本上它是这样的:

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] != '+');

它依赖于编译器的行为,在Objective-C对象上为实例和类方法添加-"或"+"前缀.其他所有内容都必须是C函数(因为C函数的名称不能以'-'或'+'开头).

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.

推荐答案

在预处理器完成所有工作的实际代码解析之前.预处理器的不能知道的功能是否是C或OBJ-C,因为它运行的代码解析之前.

The preprocessor does all of its work before the actual code is parsed. The preprocessor cannot know whether a function is C or obj-C because it runs before the code is parsed.

出于同样的原因,

if (thisFunctionIsACFunction) {
  #define SELF nil
  #define CMD nil
} else {
  #define SELF self
  #define CMD _cmd
}
DoLogging(SELF, CMD, format, ##__VA_ARGS__);

不能工作 - #定义被编译阶段之前进行处理

cannot work - the #defines are processed before the compilation stage.

因此,代码本身必须包含运行时"检查(尽管编译器可以对此进行优化).

So, the code itself must contain a "runtime" check (though the compiler may optimise this out).

我建议定义喜欢的东西

void *self = nil; //not sure about the types that
SEL _cmd = nil;   //would be valid for obj-c

在全球范围内; C函数将看到"这些定义,而Objective-C方法将希望使用它们自己的定义将其隐藏.

at global scope; the C functions will "see" these definitions while the Objective-C methods will hopefully hide them with their own definitions.

这篇关于条件宏扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆