In C++/CLI, What’s the most efficient way to convert an array of strings to native char**?
I am doing this:
array<String^>^ tokenArray = gcnew array<String^> {"TokenONE", "TokenTWO"};
int numTokens = tokenArray->Length;
char** ptr = new char* [numTokens];
for(int i = 0; i < numTokens; i++)
{
// See: http://stackoverflow.com/questions/6596242/
array<Byte>^ encodedBytes = Text::Encoding::UTF8->GetBytes(tokenArray[i]);
pin_ptr<Byte> pinnedBytes = &encodedBytes[0];
ptr[i] = reinterpret_cast<char*>(pinnedBytes);
}
int myResult = someNativeFunction(ptr, numTokens);
delete ptr;
// ...
What, if anything should be improved? Is this ok from a memory management point of view? I can change the parameters of someNativeFunction if need be.
Thank you.
Apart from the problem with pinned pointers going out of scope before being passed to
someNativeFunction(), the code can be simplified for better clarity especially if you’re using MSVC2008 or newer. See this page for information on how to convert a single string (extending to an array should be trivial).Edited:
If you need ANSI strings
const char*then making a copy is inevitable since .NET Strings are Unicode (UTF-16). On MSVC2008 and newer, your code may look as follows:This does similar job to your code sample but without the need of pointer pinning and
reinterpret_cast-ing.If you are willing to deal with wide string
const wchar_t*insomeNativeFunction(), you can use the (pinned) internal data directly, However, you’ll have to ensure the pointers remain pinned untilsomeNativeFunction()returns which, as pointed out in the comments, may negatively influence the GC performance.If you’re about to marshall many strings and performance is of utmost concern, you could
split the marshalling across several threads before passing everything to
someNativeFunction(). Before doing that, I’d reccommend profiling your application to see if the conversion really is a bottleneck or whether it’s better to focus efforts elsewhere.Edited #2:
To get the native string in UTF-8 encoding, you can do with a modified version of your code:
If you’re concerned about speed, you could pre-allocate a large buffer for the native strings (if you know there will only be a limited amount) or use pool storage.
Edited #3:(OG Dude)
Just fixed some minor typos.