c++ - 使用 Objective-C++ 和 Objective-C 的链接器问题

标签 c++ ios objective-c objective-c++

目前我有一个使用 Objective-C 的 iOS 项目。出于性能原因,我实现了如下所示的 Objective-C++ 代码:

base11.mm

#include <string>
#include "base11.h"

static const std::string characters = "0123456789_";

const char* to_base11(long n) {
    // some c++ code here
}

long from_base11(const char* input) {
    // some c++ code here
}

base11.h

#ifndef base11_h
#define base11_h

#include <stdio.h>

const char* to_base11(long n);
long from_base11(const char* input);

#endif /* base11_h */

当然,我为该类使用了 .mm 扩展名,而且我只使用普通的 C 函数参数和返回类型。

然后我有一个 Objective-C 类,它将这些 C++ 函数包装在以下方法中:

Util.m

#include "base11.h"

+(NSString*) convertBase10ToBase11:(long) base10 {
    const char* base11 = to_base11(base10);
    return [NSString stringWithUTF8String:base11];
}

+(NSNumber*) convertBase11ToBase10:(NSString*) base11 {
    const char* input = [base11 UTF8String];
    return @(from_base11(input));
}

Util.h:

@interface Util : NSObject
    +(NSString*) convertBase10ToBase11:(long) base10;
    +(NSNumber*) convertBase11ToBase10:(NSString*) base11;
@end

然而,这会产生以下编译错误:

Undefined symbols for architecture x86_64:
  "_from_base11", referenced from:
      +[Util convertBase11ToBase10:] in Util.o
  "_to_base11", referenced from:
      +[Util convertBase10ToBase11:] in Util.o
ld: symbol(s) not found for architecture x86_64

但是,这很奇怪。我选择不对 Util.m 类使用 .mm 扩展名,因为我不在那里使用任何 C++ 代码。另请注意,base11.h 头文件也未使用任何 C++ 代码。那么,为什么会出现此错误?根据这篇文章,我的方法应该是正确的:

How to call a method on .mm file from a objective c class

最佳答案

这是函数符号名称的问题。 C++ 允许具有相同名称和不同原型(prototype)的函数。 因此,当使用 C++/Objective-C++ 编译的函数时,它会获得描述它原型(prototype)的符号名称并使其独一无二。

所以你需要强制编译器使用 C 的符号名。 您可以通过在函数原型(prototype)之前添加 extern "C" 来实现。 但是如果你在 C 和 C++ 源文件中都使用这个头文件就不太方便了,因为 C 不知道它是什么extern "C"

幸运的是 CoreFoundation 已经解决了这个问题。您可以查看他们是如何声明他们的 CFString.hCFArray.h 的。

所以你只需要使用 CoreFoundation 的宏:CF_EXTERN_C_BEGINCF_EXTERN_C_END

#ifndef base11_h
#define base11_h

#include <stdio.h>
#include <CoreFoundation/CFBase.h>

CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN

const char* to_base11(long n);
long from_base11(const char* input);

CF_EXTERN_C_END
CF_IMPLICIT_BRIDGING_DISABLED

#endif /* base11_h */

关于c++ - 使用 Objective-C++ 和 Objective-C 的链接器问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53258343/

相关文章:

c++ - 奇怪的宏扩展

c++ - 在 C++ 中,您几乎一直都在做什么?

ios - 通用应用程序和在 ios 中转换 Storyboard的最佳方式是什么

ios - 我在 Xcode 5 中打开了 Xcode 4 项目。当我打开在 XC5 中打开的 View 时,标签和按钮没有显示,我该如何解决这个问题?

ios - _swift_abortRetainUnowned 将@objc 类捕获为无主时

c++ - boost::any 不能转换回 std::function

c++ - 返回 void 或非 void 类型的函数参数

ios - Swift:未使用 viewWillTransition 中调用函数的结果

ios - 使用常用方法创建类

iOS:UICollectionView 单元格选择不起作用