网络上对此有很多疑问,但我无法解决问题。我已经研究了几天。
我想在Swift项目上运行一个简单的C ++类,为此我遵循了本教程:http://www.swiftprogrammer.info/swift_call_cpp.html。 基本上,我已经遵循了以下步骤:
junk.cpp
和junk.h
文件g++ or/and clang++
$ ar r libjunkcpp.a junk.o
ranlib libjunkcpp.a
Build Phases -> Link Binary With Libraries -> Add
中的Xcode 编译时,出现以下错误:
Undefined symbols for architecture x86_64:
"A::getInt()", referenced from:
_getIntFromCPP in wrapper.o
"A::A(int)", referenced from:
_getIntFromCPP in wrapper.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
junk.h
class A {
public:
A(int);
int getInt();
private:
int m_Int;
};
junk.cpp
#include "junk.h"
A::A(int _i) : m_Int(_i) {}
int A::getInt() {
return m_Int
}
wrapper.cpp
#include "junk.h"
extern "C" int getIntFromCPP() {
// Create an instance of A, defined in
// the library, and call getInt() on it:
return A(1234).getInt();
}
bridge.h
int getIntFromCPP();
答案 0 :(得分:0)
这是在使用通过 Objective-C 桥接到 Swift 的 C 或 C++ 库时有时会发生的问题。问题不在于存档(静态库)的构建方式,而是创建应用程序的过于激进的链接器的问题。
问题是链接器看到绑定符号和 C++ 符号,但从未看到它被从任何地方调用,因为它实际上是从不同的语言 (Swift) 调用的。这最终会导致链接器积极地剥离所有它认为不会被使用的符号以节省空间,从而有效地删除所有 C++ 代码。
发生这种情况时,nm
将报告存档中存在的正确符号,但由于找不到符号,实际应用程序将无法执行。
至于解决方案,实际上 Stack Overflow 上已经有几个问题/答案在不同程度上解决了这个问题:
How to disable C++ dead code stripping in xcode,其中解决方案是使用链接器标志 -force_load
来强制静态符号被实际加载。
Keeping Xcode from stripping out unused symbols from a static library,更广泛地建议切换一些可能导致符号不被剥离的 Xcode 配置。但是,此处答案中的建议可能与上述两个链接发生冲突。
如果没有关于现有设置的更多信息,例如 __attribute__((constructor))
在哪里构建,以及如何在 Swift 项目中使用绑定,很难提供明确而明确的答案。鉴于这个问题是从 2018 年开始的,我不怀疑会有更多关于当时这种设置的信息。
从描述的症状来看,这听起来与我的同事在进行 C++/Swift 绑定时遇到的问题完全一样——最终的解决方案是使用 wrapper.cpp
来确保存档完整地保留到最终应用程序中.