从 C++ std::string& 获取 unichar * 以在 Objective-C++ 中创建非空 NSString



我有一些Objective-C++来包装现有的C++库。C++库偶尔会给我std::string&参数,我想将这些参数转换为nonnullNSString。几乎所有NSString初始值设定项都返回nullable NSString,除了:-initWithCharactersNoCopy:length:freeWhenDone:-initWithCharacters:length:。但是,这两者都需要unichar *,但std::string.c_str()返回char *

如何从C++std::string获取unichar *,以便创建NSString * _Nonnull

不是重复的

其他问题只是想从std::string转换为NSString。我想知道是否可以在不产生nullNSString *的情况下这样做,可能是通过在std::string上调用方法来获得unichar *std::wstring_convert看起来很有前途,但我不是一个C++开发人员,所以我还不知道如何开始。

可能的解决方案

经过进一步研究,我了解到std::string只是一个std::basic_string<char>,似乎你可以定义自己的std::basic_string。我找到了一个类似的例子,可以转换为std::wstring

// std::string -> std::wstring
std::string s("string");
std::wstring ws;
ws.assign(s.begin(), s.end());

所以我把它改编成std::basic_string<unichar>,编译得很好:

void Foo(const std::string& bar) {
std::basic_string<unichar> barUnichar;
barUnichar.assign(bar.begin(),
bar.end());
NSString * _Nonnull barNSString = 
[NSString stringWithCharacters:barUnichar.c_str() 
length:barUnichar.length()];
NSLog(@"bar: %@", bar);
}

我不介意从std::string转换为std::basic_string<unichar>执行不必要的复制,我想一旦我了解有关内存所有权规则的更多信息,我就可以更改上面的代码以使用C++-[NSString initWithCharactersNoCopy:length:freeWhenDone:]

可能的解决方案不好

乔·格罗夫在推特上说:

这将进行逐字节映射。它可能适用于 ASCII,但 会给你任何Unicode的垃圾。

让我们再试一次,看看它是否对您有帮助。您已经编辑了该问题以响应建议,它是重复的并添加了:

其他问题只是想从std::string转换为NSString。我想知道是否可以在不产生nullNSString *的情况下做到这一点......

直接答案:不

原因很简单:Objective-C库不能假设传递给它的任何指针都引用有效编码的C字符串,即使该指针是std::string键入的。

现在你可能非常有信心,你的C++代码永远不会给你一个无效编码的字符串——可以说信心是合理的(但毕竟是C++;-))——所以相信空结果永远不会发生,但这并不能改变Objective-C库不能假设它不会发生的事实。

DIY答案:是的

尝试避免空值,例如尝试将std::string转换为unichar *等,就像您所考虑的那样,只是避免了这个问题 - 某处的某些代码必须处理检查编码或冒返回无效编码NSString的风险。

虽然可以做到这一点,但与 DIY 方法相比,它既会更加复杂,并且可能会让您不知道无效编码会返回什么:只需在源代码中自己处理 null 返回并用其他内容替换它。例如:

std::string someCstring;
NSString *convertedString = @(someCstring.c_str()) ?: @"ERROR: C string is invalid UTF8";

在这里convertedString永远不会nil.

(如果你的 C 字符串不是 UTF8,你将需要使用另一个接受编码的NSString初始化器。

呵呵

相关内容

  • 没有找到相关文章

最新更新