2011-12-24 71 views
1

我增加了行extern "C" void perlinTest(void);到C++头随着包括C头文件,希望这是所有我需要的,但编译器会抱怨的:如何从iPhone的C++代码中调用C函数?

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

您还需要链接任何库提供的功能。 – Mat 2011-12-24 20:46:41

+0

这不是图书馆。我写了c函数和调用它的C++代码。 – Xavier 2011-12-24 20:49:04

+0

然后,您需要确保C代码已编译并与您的C++代码链接。 – Mat 2011-12-24 20:50:49

回答

1

您的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 
0

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

0

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

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

只要您尝试从其他类中的其中一个类中调用perlinTest()(例如从CreateRenderer3(IResourceManager*) in Renderer.o),链接器将希望确定该符号可以被解析,并且如果您没有实际实现它的准系统定义(见下文),那么你可能会得到一个像你得到的错误。

最小实现类似下面应防止连接错误:

void perlinTest(void) { 

} 
+0

是的,我已经实施。 – Xavier 2011-12-24 21:10:19

0

一个窍门,你可以用它来调试,这是在你的perlinTest()功能引入故意的错误。然后构建您的应用并查看编译器是否报告错误。如果应用程序编译无论如何,那么你的问题是,具有此功能的文件不是你正在构建的目标的一部分。

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

编辑:下一步是检查由Xcode发出的链接命令是否包含具有C函数的.o。如果确实如此,那么您应该使用nm工具转储.o文件的内容,以查看.o中函数名称的外观。

+0

包含perlinTest的文件在引入错误后未编译。 – Xavier 2011-12-24 22:37:23

+0

是的,我正在编译iPhone模拟器。 – Xavier 2011-12-24 22:37:53