【发布时间】:2026-01-09 15:50:01
【问题描述】:
短版:
如何将std::string(使用桥接从 .Swift 文件调用的 .cpp 函数返回的对象)转换为 Swift String?
加长版:
我有一个用 C++ 编写的库,我必须使用 Swift 调用一些代码。我创建了一个桥,在我的 Xcode 项目中添加了两个文件:
一个桥接头,它允许 Swift 调用 C 函数(afaik 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*并将所有权授予调用者。 -
也许一个解决方案是在 getStringFromLibrary() 中调用 malloc 为
char *变量分配内存,将变量的内容复制到 Swift 字符串,然后显式调用free() -
@Nisba 是的,这是通常的方法。您可以考虑添加一个
freeStringFromLibrary函数,而不是直接从Swift 调用free,以便隐藏内存分配的底层方法。这会让你在内部使用new[]或malloc。
标签: c++ swift static-libraries bridge