简短版:
如何将从使用桥接调用的 .cpp 函数返回的 std::string
对象转换为 Swift 的 String
?
详细版:
我有一个用 C++ 编写的库,我必须使用 Swift 调用一些代码。我创建了一个桥接,在我的 Xcode 项目中添加了两个文件:
一个桥接头文件,允许 Swift 调用 C 函数(据我所知,Swift 不能直接调用 C++ 函数,因此需要通过 C 函数传递)
//file bridgingHeader.h
const char * getLastOpenedFile();
还有一个 .cpp 文件,它可以调用 C++ 函数,并且可以使用 extern "C" 定义 C 函数。
//file wrapper.cpp
#include <string>
#include "my_library.hpp"
extern "C" const char * getStringFromLibrary()
{
const char * s = get_string_from_library().c_str();
return s;
}
我可以使用以下方法访问 .swift 文件的返回值:
let myString = String(cString: getStringFromLibrary())
Swift.print(myString)
在函数
getStringFromLibrary()
内设置断点来检查变量 s
的值,可以查看字符串的内容,这证明库函数已正确调用。但是,.swift 文件打印了一些奇怪的符号而不是原始字符串。 将
getStringFromLibrary()
更改为以下内容。extern "C" const char * getStringFromLibrary()
{
return get_string_from_library().c_str();
}
由于 Swift 代码打印真实字符串的前缀,我认为这是一个内存问题:很可能当 getStringFromLibrary()
结束时,get_string_from_library()
返回的 std::string
对象被销毁,因此通过 .c_str()
返回的指针所指向的内存不再可靠,这就是我从 Swift.print()
得到错误输出的原因。
从 .swift 文件中访问 std::string
并释放其内存的正确方法是什么?
getStringFromLibrary
函数将会持有一个悬空指针,因为s
是指向get_string_from_library
函数分配并销毁的const char*
。我不熟悉 Swift,但你需要在堆上分配那个const char*
并将所有权交给调用者。 - Cory Kramerchar*
变量分配内存,将变量的内容复制到Swift字符串中,然后显式地调用free()
。 - NisbafreeStringFromLibrary
函数,而不是直接从 Swift 调用free
,这样就可以隐藏内存分配的底层方法。这将让你在内部使用new[]
或malloc
。 - Miles Budnek