【发布时间】:2011-03-03 03:40:50
【问题描述】:
请注意:这是一个奇怪的问题。
我有一些非常有用的宏,我喜欢用它们来简化一些日志记录。例如我可以做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*,这可能是我请求帮助的主要障碍。
【问题讨论】:
-
你是怎么想出
thisFunctionIsACFunction的? -
@Artelius 编辑问题并提供更多信息
标签: c objective-c macros conditional