将 std::string 转换为 Swift 字符串

Nis*_*sba 3 c++ bridge static-libraries swift

精简版:

如何将std::string(使用桥接从 .Swift 文件调用的 .cpp 函数返回的对象)转换为 Swift String

长版:

我有一个用 C++ 编写的库,我必须使用 Swift 调用一些代码。我创建了一个桥,在我的 Xcode 项目中添加了两个文件:

一个桥接头,它允许 Swift 调用 C 函数(afaik Swift 不能直接调用 C++ 函数,所以它需要通过 C 函数)

//file bridgingHeader.h
const char * getLastOpenedFile();
Run Code Online (Sandbox Code Playgroud)

和一个 .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;
}
Run Code Online (Sandbox Code Playgroud)

我可以使用 .swift 文件访问返回值

let myString = String(cString: getStringFromLibrary())
Swift.print(myString)
Run Code Online (Sandbox Code Playgroud)

放置断点检查s函数内部的值getStringFromLibrary()我可以看到字符串的内容,因此库中的函数被正确调用。

无论如何, .swift 文件会打印一些奇怪的符号而不是原始字符串。更改getStringFromLibrary()为以下

extern "C" const char * getStringFromLibrary()
{        
    return get_string_from_library().c_str();
}
Run Code Online (Sandbox Code Playgroud)

我的结果是 .swift 代码打印了真实字符串的前缀。这让我想到了一个内存问题:可能在getStringFromLibrary()退出时,std::string返回的对象get_string_from_library()被销毁,因此返回的指针指向的内存.c_str()不再可靠,这是为什么我从Swift.print().

std::string从 .swift 文件访问一个然后释放其内存的正确方法是什么?

OOP*_*Per 5

您可以编写一个 Objective-C++ 包装器来处理 C++ 代码。

桥接头:

#include "Wrapper.hpp"
Run Code Online (Sandbox Code Playgroud)

包装器.hpp:

#ifndef Wrapper_hpp
#define Wrapper_hpp

#import <Foundation/Foundation.h>

#if defined(__cplusplus)
extern "C" {
#endif
    NSString * _Nonnull getStringFromLibrary();
#if defined(__cplusplus)
}
#endif

#endif /* Wrapper_hpp */
Run Code Online (Sandbox Code Playgroud)

包装.mm:

#include "Wrapper.hpp"

#include <string>
#include "my_library.hpp"

NSString * _Nonnull getStringFromLibrary() {
    return [NSString stringWithUTF8String:get_string_from_library().c_str()];
}
Run Code Online (Sandbox Code Playgroud)

SWIFT代码:

print(getStringFromLibrary())
Run Code Online (Sandbox Code Playgroud)

[NSString stringWithUTF8String:]将缓冲区的内容复制到一些内部存储中,ARC 管理释放它。您无需定义free_something().