调用Objective-C++中的C函数导致链接错误

26

我遇到了一个奇怪的链接器问题。我的代码看起来像这样:

    double given_amount = self.modelController.levelCompleteRewardAmount;
    swrve_currency_given(swrve, (CFStringRef)@"currencyName", given_amount);

我有这段代码在两个不同的地方:一个是Objective-C文件,另一个是Objective-C++文件。它在Objective-C文件中编译正常,但是在我的WGController.mm文件中,swrve_currency_given()函数导致以下问题:

Undefined symbols for architecture armv7:
  "swrve_currency_given(Swrve*, __CFString const*, double)", referenced from:
      -[WGController giveTheUserSomeCashForPlayingThisLevel] in WGController.o
ld: symbol(s) not found for architecture armv7
collect2: ld returned 1 exit status

我不确定这个错误是否与Obj-C和C++相关,但是它给我一种这样的感觉。我的理论是它可能认为它是Obj-C类上的函数?'swrve' 代码是第三方代码,有一个.h和.c文件,我是这样导入的:

#import "swrve.h"

感谢任何帮助!


你也在项目中为链接器导入它吗?进入你的目标属性,打开总览页面上的“链接框架和库”。swrve 库应该在那里;如果没有的话,请添加它并尝试重新编译。 - Sergey Kalinichenko
该库不是静态库/框架,只是一个.c和.h文件。(我已更新我的问题以反映这一点)。 - Chris Hill
2个回答

48

你可能需要在函数原型周围加上:

#if defined __cplusplus
extern "C" {
#endif

void swrve_currency_given (...whatever goes here...);

#if defined __cplusplus
};
#endif

这告诉编译器它是一个C函数而不是C++函数。


看起来它工作了,但是添加的样板代码太多了!谢谢! - Chris Hill
我添加了一个使用extern"C"语法变量的版本,它没有块作用域,我认为更加简洁,因为您只需要执行模板操作一次。这有点太大了,无法在评论中发布,但是修改应该很快被批准。 - pmdj
为了澄清答案,让后人能够理解:您需要将此代码添加到C代码的.h文件中。 - Winston Du

9

如果你在C++文件中使用C函数,你应该使用extern "C"{}。在.h文件中。

#ifdef __cplusplus
extern "C" {
#endif

swrve_currency_given(parameter1, parameter2, parameter3);// a c function


#ifdef __cplusplus
}
#endif  

extern "C"是为了让C++编译器识别,并通知编译器注意被标记的函数是(或将被)以C语言风格编译。

如果您链接的库是由C代码编译而成的,请使用

extern "C" {
  #include "c_only_header.h"
}

请看C++中何时使用extern "C"?

这篇文章。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接