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

How do you call a C function from C++ code in the iPhone?

本文关键字:代码 调用 函数 C++ 中的 iPhone      更新时间:2023-10-16

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

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

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

extern "C" [prototype];

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

extern "C" void perlinTest();

这样做的原因是C++函数名称被修改为告知参数类型的内容。在最低级别,这就是允许重载的原因:拥有两个共享相同名称的可见符号从来都不是合法的,因此C++通过嵌入指示函数名称中参数类型的标记来允许它们。例如,void perlinTest()在我的狮子盒子上被g++(可能clang++(破坏为_Z10perlinTestv,尽管这是特定于 ABI 的,在其他平台上不一定相同。

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

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

#ifdef __cplusplus
extern "C" {
#endif
/* header body */
#ifdef __cplusplus
}
#endif

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

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

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

一旦您尝试从其他类之一(例如从 CreateRenderer3(IResourceManager*) in Renderer.o(调用 perlinTest(),链接器就会希望确保可以解析该符号,如果您实际上还没有实现它的准系统定义(见下文(,那么您可能会收到类似您得到的错误。

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

void perlinTest(void) {
}

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

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

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