如何在Cocoa框架中防止C++名称篡改

How to prevent C++ name mangling in a Cocoa framework

本文关键字:C++ Cocoa 框架      更新时间:2023-10-16

我在Cocoa Framework中创建了一个要导出的函数。这个函数是在ObjectiveC++中实现的,C++的名称篡改让我抓狂。

我已经在外部"C"块中声明了该函数,但没有用。

这是我在框架中的头文件:

#import <Cocoa/Cocoa.h>
extern "C"{
    void display(NSString *text);
}
@interface Display : NSObject
@end

这就是.mm文件:

#import "Display.h"
#include <string>
#include <iostream>
using namespace std;
void display(NSString *text){
    cout << [text cStringUsingEncoding:NSUTF8StringEncoding] << endl;
}
@implementation Display

@end

它编译得很好,没有任何错误。

在客户端,我添加了框架,导入了暴露的头,并尝试调用函数:

display(@"Hola");

这里我收到一个警告,抱怨"C99中函数显示的隐式声明无效"

雪上加霜的是,在暴露的头文件中,我在extern"C"行中得到了一个错误(没有显示在框架项目中):

"预期标识符或("

还有什么必要让这件事继续下去?

您需要将extern "C"添加到函数实现和声明中。如果函数的实现在.mm(Objective-C++)文件中,它将被编译为Objective-CC++,并带有名称篡改。对于具有相同名称的函数,您碰巧有一个extern "C"声明,这并不重要。他们仍然被视为两个不同的东西。

因此,将您的实现封装在extern "C"中,以消除函数实现的名称篡改:

extern "C" void display(NSString *text) {
}

或者:

extern "C" {
    void display(NSString *text) {
    }
}

此外,如果您希望C代码可以使用您的头,则需要添加一个#ifdef,以便在编译为C++时仅使用externextern不是C:中的有效关键字

#ifdef __cplusplus
    extern "C" {
#endif
void display(NSString *text);
#ifdef __cplusplus
    }
#endif

请参阅组合C++和C-#ifdef__cplusplus是如何工作的?了解更多信息。