Objective C
的一个主要功能很简单introspection。此功能的典型用途是能够在调用之前检查某些方法(函数),以确保它确实存在。
以下代码将在运行时抛出错误(尽管编译就好了(Apple LLVM version 7.0.2 (clang-700.1.81)
))...
@import Foundation;
@interface Maybe : NSObject + (void) maybeNot; @end
@implementation Maybe @end
int main (){ [Maybe maybeNot]; }
通过在通话前添加一个简单的条件......
if ([Maybe respondsToSelector:@selector(maybeNot)])
我们可以等到运行时来决定是否调用该方法。
有没有办法用"标准" C
(c11
)或C++
(std=c14
)?
...即
extern void callMeIfYouDare();
int main() { /* if (...) */ callMeIfYouDare(); }
我想我还应该提一下,我正在测试/使用它是在Darwin
运行时环境中。
答案 0 :(得分:2)
在GNU gcc / Mingw32 / Cygwin上,您可以使用Weak symbol:
#include <stdio.h>
extern void __attribute__((weak)) callMeIfYouDare();
void (*callMePtr)() = &callMeIfYouDare;
int main() {
if (callMePtr) {
printf("Calling...\n");
callMePtr();
} else {
printf("callMeIfYouDare() unresolved\n");
}
}
编译并运行:
$ g++ test_undef.cpp -o test_undef.exe
$ ./test_undef.exe
callMeIfYouDare() unresolved
如果您将它与定义callMeIfYouDare的库链接,尽管它会调用它。请注意,至少在Mingw32 / Cygwin中需要通过指针。直接调用callMeIfYouDare()将默认导致截断重定位,除非您想要使用链接描述文件是不可避免的。
使用Visual Studio,您可以使用__declspec(selectany)来执行相同的操作:GCC style weak linking in Visual Studio?
更新#1:对于XCode,您可以使用__attribute__((weak_import))
代替:Frameworks and Weak Linking
更新#2:对于基于&#34; Apple LLVM 6.0版(clang-600.0.57)的XCode(基于LLVM 3.5svn)&#34;我设法通过使用以下命令进行编译来解决问题:
g++ test_undef.cpp -undefined dynamic_lookup -o test_undef
并保留其他平台的__attribute__((weak))
。
答案 1 :(得分:1)
C ++或C没有内省。您可以在附加图层中添加一些内容(例如,请查看Qt metaobject或GTK GObject introspection);您可以考虑使用GCC自定义MELT以获得一些内省......(但这需要数周时间)。您可以使用一些额外的脚本或工具来发出与您的内省需求相关的C或C ++代码(SWIG可能是鼓舞人心的)。
在您的特定情况下,您可能希望使用weak symbols(至少在Linux上)。也许使用相关的function attribute代码。
extern void perhapshere(void) __attribute__((weak));
if (perhapshere)
perhapshere();
你甚至可以用一些宏来缩短它。
也许您只想加载一些dlopen(3)插件并使用dlsym(3)在其中找到符号(或者甚至在整个程序中使用-rdynamic
,通过提供NULL
的{{1}}路径,并在获取的句柄上使用dlopen
;请注意,C ++使用name mangling。
所以你可以试试
dlsym
然后:
void*mainhdl = dlopen(NULL, RTLD_NOW);
if (!mainhdl) { fprintf(stderr, "dlopen failed %s\n", dlerror());
exit(EXIT_FAILURE); };
答案 2 :(得分:1)
如果可以看到在源代码中调用对象(而不是指针)的函数并且代码编译成功 - 则该函数确实存在且不需要检查。
如果通过指针调用函数,则假定您的指针是具有该函数的类的类型。要检查它是否如此,请使用强制转换:
auto* p = dynamic_cast<YourClass*>(somepointer);
if (p != nullptr)
p->execute();