我增加了行extern "C" void perlinTest(void);
到C++头随着包括C头文件,希望这是所有我需要的,但编译器会抱怨的:如何从iPhone的C++代码中调用C函数?
Undefined symbols for architecture i386:
"perlinTest()", referenced from:
CreateRenderer3(IResourceManager*) in Renderer.o
我增加了行extern "C" void perlinTest(void);
到C++头随着包括C头文件,希望这是所有我需要的,但编译器会抱怨的:如何从iPhone的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++ function names are mangled的东西,讲述的类型参数。在最底层,这是允许重载的:它有两个可见的符号共享相同的名字是不合法的,所以C++通过在函数名称中嵌入指示参数类型的标记来允许它们。例如,void perlinTest()
在我的Lion box上被_Z10perlinTestv
改为g++
(可能是clang++
),虽然这是ABI特有的,并不一定在其他平台上相同。
但是,C不支持重载,并且函数不受名称的限制,所以当C++代码试图调用它时,它需要知道它不能使用重名。这是extern "C"
告诉编译器。
如果您的头文件需要从C和C可读++时,通常的做法是将它们包装在一个extern "C"
块(extern "C" { /* declarations */ }
)本身包裹在一个#ifdef __cplusplus
预处理器指令(因此C代码不会看到extern "C"
码)。
#ifdef __cplusplus
extern "C" {
#endif
/* header body */
#ifdef __cplusplus
}
#endif
如果它不是一个库,你不需要任何extern C.我将转向.c文件扩展名,以及如何将您的编译器配置为识别它(看起来不像.c代码)
您是否确实在任何地方实施了void perlinTest(void)
?
最初,您可能只需声明函数而不必实际执行它。如果没有其他类/对象实际调用perlinTest()
,Xcode将很乐意构建和运行您的应用程序,而不会发出任何错误。由于perlinTest()
实际上并未从任何地方引用,因此它并不关心该函数是否未实际实现。
只要您尝试从其他类中的其中一个类中调用perlinTest()
(例如从CreateRenderer3(IResourceManager*) in Renderer.o
),链接器将希望确定该符号可以被解析,并且如果您没有实际实现它的准系统定义(见下文),那么你可能会得到一个像你得到的错误。
最小实现类似下面应防止连接错误:
void perlinTest(void) {
}
是的,我已经实施。 – Xavier 2011-12-24 21:10:19
一个窍门,你可以用它来调试,这是在你的perlinTest()
功能引入故意的错误。然后构建您的应用并查看编译器是否报告错误。如果应用程序编译无论如何,那么你的问题是,具有此功能的文件不是你正在构建的目标的一部分。
另请注意,您粘贴的错误是针对i386架构的,因此它不能是iPhone。相反,您可能正在为iPhone模拟器构建。
编辑:下一步是检查由Xcode发出的链接命令是否包含具有C函数的.o。如果确实如此,那么您应该使用nm工具转储.o文件的内容,以查看.o中函数名称的外观。
您还需要链接任何库提供的功能。 – Mat 2011-12-24 20:46:41
这不是图书馆。我写了c函数和调用它的C++代码。 – Xavier 2011-12-24 20:49:04
然后,您需要确保C代码已编译并与您的C++代码链接。 – Mat 2011-12-24 20:50:49