问题描述
我正在开发 C++ 和 Swift 之间的桥梁。所以我需要将 C++ u32 字符串转换为 swift 字符串。这是有问题的代码:
int count = linesProvider->getdisplayLinesCount();
NSMutableArray *lines = [[NSMutableArray alloc] initWithCapacity:static_cast<NSUInteger>(count)];
for (int i = 0; i < count; ++i) {
std::u32string_view line = linesProvider->getdisplayedLineAt(i);
Nsstring* objCline = [[Nsstring alloc] initWithBytesNocopy:(void*)line.data()
length:line.size() * sizeof(char32_t)
encoding:NSUTF32StringEncoding freeWhenDone:NO];
[lines addobject:objCline];
}
在调试时我发现 objCline 为零。做错了什么?
我的调试方法如下:
解决方法
如果您使用该方法的 initWithBytes:
变体,您的字符串数据是否被接受?
失败的原因是您提供了 CFString
不喜欢的字符串数据(在这种情况下上述复制变体也会失败),或者 CFString
根本不支持UTF-32 作为内部表示,因此必须始终复制它们。我怀疑是后者。
如果您想确定,可以在此处搜索旧版 CFStringCreateWithBytesNoCopy()
函数(NSString
最终调用的函数)的源代码:
https://opensource.apple.com/source/CF/CF-1151.16/CFString.c.auto.html
它调用了相当长的 __CFStringCreateImmutableFunnel3()
函数,需要一段时间才能解开。您可以编译您自己的该函数版本,并在调试器中逐步执行以找出导致 return NULL
的情况。
(顺便说一句,我怀疑 …NoCopy
语义在通用 Swift 包装器中很难安全地维护,因此无论如何允许复制可能是更好的方法 - 例如,CFString
假设传入的内存永远不会被修改,对于C++字符串当然不一定如此。)