你如何从iPhone中的C ++代码调用C函数?

时间:2011-12-24 20:43:20

标签: iphone c++ c ios xcode

我将行extern "C" void perlinTest(void);添加到C ++标题以及c头文件的包含中,希望这是我所需要的但是编译器抱怨:

Undefined symbols for architecture i386:
  "perlinTest()", referenced from:
      CreateRenderer3(IResourceManager*) in Renderer.o

4 个答案:

答案 0 :(得分:1)

您的C ++代码需要知道该函数是C函数。为此,您需要以这种方式声明:

extern "C" [prototype];

您的情况的一个现实例子是:

extern "C" void perlinTest();

这样做的原因是C++ function names are mangled告诉了参数的类型。在最低级别,这是允许重载的原因:拥有两个共享相同名称的可见符号从来都不合法,因此C ++通过嵌入指示函数名称中参数类型的标记来允许它们。例如,void perlinTest()在我的Lion框中被_Z10perlinTestvg++(可能是clang++)混淆为extern "C",尽管这是ABI特定的,并且不一定相同其他平台。

但是,C不支持重载,并且函数不受名称修改的影响,因此当您的C ++代码尝试调用它时,它需要知道它不能使用损坏的名称。这是extern "C"告诉编译器的内容。

如果您的头文件需要可以从C和C ++中读取,通常的做法是将它们包装在extern "C" { /* declarations */ }块(#ifdef __cplusplus)本身包装在extern "C"预处理器指令中(因此C代码没有看到#ifdef __cplusplus extern "C" { #endif /* header body */ #ifdef __cplusplus } #endif 代码)。

{{1}}

答案 1 :(得分:0)

如果它不是库,则不需要任何extern C.我将转向.c文件扩展名以及编译器如何配置识别它(看起来不像.c代码)

答案 2 :(得分:0)

您是否实际在任何地方实施了void perlinTest(void)

最初,您可能只需要声明该函数而无需实际执行它。如果您的其他类/对象都没有实际调用perlinTest(),Xcode将很乐意构建并运行您的应用程序,而不会发出任何错误。由于perlinTest()实际上并未从任何地方引用,因此并不关心该函数是否实际实现。

只要您尝试从其他类(例如perlinTest())调用CreateRenderer3(IResourceManager*) in Renderer.o,链接器就会确保可以解析符号,如果没有实际上实现了它的准系统定义(见下文),然后你可能会得到一个像你得到的错误。

如下所示的最小实现应该可以防止链接错误:

void perlinTest(void) {

}

答案 3 :(得分:0)

您可以用来调试此问题的一个技巧是在perlinTest()函数中引入故意错误。然后构建您的应用程序,看看编译器是否报告错误。如果应用程序仍在编译,那么您的问题是具有此功能的文件不是您正在构建的目标的一部分。

另请注意,您粘贴的错误是针对i386架构的,因此它不能是iPhone。你可能正在构建iPhone模拟器。

编辑:下一步是检查Xcode发出的链接命令是否包含具有C功能的.o。如果是,那么你应该使用nm实用程序转储.o文件的内容,以查看.o中函数名称的含义。