抬头:这是一个奇怪的问题。
我有一些非常有用的宏,我喜欢用来简化一些日志记录。例如,我可以执行Log(@"My message with arguments: %@, %@, %@", @"arg1", @"arg2", @"arg3")
,这将扩展为更复杂的方法调用,其中包括self
,_cmd
,__FILE__
,__LINE__
等内容,等,以便我可以轻松跟踪记录的内容。这很有效。
现在我想扩展我的宏,不仅可以使用Objective-C方法,还可以使用常规的C函数。问题是宏扩展中的self
和_cmd
部分。 C函数中不存在这两个参数。理想情况下,我希望能够在C函数中使用同一组宏,但我遇到了问题。当我使用(例如)我的Log()
宏时,我收到关于self
和_cmd
未声明的编译器警告(这完全有道理)。
我的第一个想法是做以下事情(在我的宏中):
if (thisFunctionIsACFunction) {
DoLogging(nil, nil, format, ##__VA_ARGS__);
} else {
DoLogging(self, _cmd, format, ##__VA_ARGS__);
}
这仍会产生编译器警告,因为整个if()语句被替换代替宏,导致self
和_cmd
关键字出错(即使它们永远不会执行功能执行)。
我的下一个想法是做这样的事情(在我的宏观中):
if (thisFunctionIsACFunction) {
#define SELF nil
#define CMD nil
} else {
#define SELF self
#define CMD _cmd
}
DoLogging(SELF, CMD, format, ##__VA_ARGS__);
不幸的是,这不起作用。我在第一个#define
上收到“错误:'#'后面没有宏参数”。
我的另一个想法是创建第二组宏,专门用于C函数。这令人厌恶的代码味道,我真的不想这样做。
有什么方法可以在Objective-C方法和C函数中使用同一组宏,如果宏在Objective-C方法中,则只引用self
和_cmd
?
修改更多信息:
thisFunctionIsACFunction
以一种非常基本的方式确定(我绝对愿意接受改进和建议)。基本上是这样的:
BOOL thisFunctionIsACFunction == (__PRETTY_FUNCTION__[0] != '-' && __PRETTY_FUNCTION__[0] != '+');
它依赖于编译器的行为,为Objective-C对象的实例和类方法添加' - '或'+'。其他任何东西都必须是C函数(因为C函数的名称不能以' - '或'+'开头)。
据我所知,此检查在技术上是运行时检查,因为__PRETTY_FUNCTION__
被char*
取代,这可能是我请求帮助的主要障碍。
答案 0 :(得分:7)
预处理器在解析实际代码之前完成所有工作。预处理器不能知道函数是C还是obj-C,因为它在解析代码之前运行。
出于同样的原因,
if (thisFunctionIsACFunction) {
#define SELF nil
#define CMD nil
} else {
#define SELF self
#define CMD _cmd
}
DoLogging(SELF, CMD, format, ##__VA_ARGS__);
无效 - 在编译阶段之前处理#defines。
因此,代码本身必须包含“运行时”检查(尽管编译器可能会对此进行优化)。
我建议定义类似
的内容void *self = nil; //not sure about the types that
SEL _cmd = nil; //would be valid for obj-c
在全球范围内; C函数将“看到”这些定义,而Objective-C方法有望用自己的定义隐藏它们。
答案 1 :(得分:1)
您可以使用
if defined "abc" <statement1>
else if defined "def" <statement2>
答案 2 :(得分:0)
您可以使用某种宏条件:
#ifndef OBJECTIVE_C
#define self 0
#define _cmd ""
#endif
我不太确定你应该定义什么self
和_cmd
,这些只是猜测。
我不确定是否有预定义的宏可以检查您是否在Objective C中进行编译,因此您可能需要手动定义OBJECTIVE_C
作为构建的一部分。