У меня есть Objective-C ++, который оборачивает существующую библиотеку C ++. Библиотека C ++ иногда дает мне std::string&
параметры, которые я хочу преобразовать в nonnull
NSString
s. Почти все NSString
возврат инициализаторов nullable NSString
с исключением: -initWithCharactersNoCopy:length:freeWhenDone:
а также -initWithCharacters:length:
, Тем не менее, оба из них требуют unichar *
, но std::string.c_str()
возвращается char *
,
Как я могу получить unichar *
из C ++ std::string
так что я могу создать NSString * _Nonnull
?
Не дубликат
Другие вопросы просто хочу конвертировать из std::string
в NSString
, Я хочу знать, возможно ли это сделать без null
NSString *
возможно, вызывая методы на std::string
получить unichar *
, std::wstring_convert
выглядит многообещающе, но я не разработчик C ++, поэтому я пока не знаю, как с этим начать.
Возможное решение
После дальнейших исследований я узнал, что std::string
это просто std::basic_string<char>
и кажется, что вы можете определить свой собственный std::basic_string
s. Я нашел Подобный пример, который преобразуется в 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>
выполняет ненужное копирование, и я думаю, что я могу изменить приведенный выше код для использования -[NSString initWithCharactersNoCopy:length:freeWhenDone:]
как только я узнаю больше о правилах владения памятью в C ++.
Возможное решение не хорошо
Это будет делать побайтовое отображение. Это может работать для ASCII, но
даст вам мусор для любого Unicode.
Давайте попробуем еще раз, посмотрим, поможет ли это вам. Вы отредактировали вопрос в ответ на предположение, что это дубликат, и добавили:
Другие вопросы просто хочу конвертировать из
std::string
вNSString
, Я хочу знать, возможно ли это сделать безnull
NSString *
…
Прямой ответ: нет
Причина проста: библиотека Objective C не может предположить, что любой переданный ей указатель ссылается на правильно закодированную строку C, даже если этот указатель напечатан std::string
,
Теперь вы можете быть очень уверены, что ваш код C ++ никогда не передаст вам неверно закодированную строку — и можно утверждать, что уверенность является разумной (но в конце концов это C ++ ;-)) — и поэтому верьте, что нулевой результат никогда не произойдет , но это не меняет того факта, что библиотека Objective C не может предположить, что не будет.
Сделай сам ответ: да
Попытка избежать нуля, например пытаясь преобразовать std::string
в unichar *
и т. д., как вы уже рассматривали, просто избегает этой проблемы — некоторый фрагмент кода где-то имеет дело с проверкой кодировки или с риском возврата неверно закодированного NSString
,
В то время как это может быть возможно, в обоих случаях это будет более сложным делом и может привести к тому, что вы не будете знать, что возвращается за неправильные кодировки, по сравнению с подходом «сделай сам»: просто разберитесь с нулем, верните себя в источнике и замените его чем-то другим. Например:
std::string someCstring;
NSString *convertedString = @(someCstring.c_str()) ?: @"ERROR: C string is invalid UTF8";
Вот convertedString
никогда не будет nil
,
(Если ваша строка C не UTF8, вам нужно будет использовать другую NSString
инициализатор, который принимает кодировку.)
НТН
Других решений пока нет …