I have some Objective-C++ that wraps an existing C++ library. The C++ library occasionally gives me std::string&
parameters that I want to convert into nonnull
NSString
s. Almost all of the NSString
initializers return nullable NSString
s except: -initWithCharactersNoCopy:length:freeWhenDone:
and -initWithCharacters:length:
. However, both of those require unichar *
, but std::string.c_str()
returns char *
.
How can I get a unichar *
from a C++ std::string
so that I can create an NSString * _Nonnull
?
Not a duplicate
Other questions simply want to convert from std::string
to NSString
. I want to know if it's possible to do so without producing a null
NSString *
, possibly by calling methods on std::string
to get unichar *
. std::wstring_convert
looks promising, but I'm not a C++ developer, so I don't know how to get started with that yet.
Possible solution
After researching further, I learned that std::string
is just a std::basic_string<char>
, and it seems like you can define your own std::basic_string
s. I found a similar example that converts to std::wstring
:
// std::string -> std::wstring
std::string s("string");
std::wstring ws;
ws.assign(s.begin(), s.end());
So I adapted it to std::basic_string<unichar>
, and it compiles fine:
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);
}
I don't mind that converting from std::string
to std::basic_string<unichar>
performs a needless copy, and I imagine I can change the above code to use -[NSString initWithCharactersNoCopy:length:freeWhenDone:]
once I learn more about C++ memory ownership rules.
Possible solution is no good
That's going to do a byte-by-byte mapping. It may work for ASCII but will give you garbage for any Unicode.