[英]Conversion of C++/CLI array of strings to native C++ char**
在C ++ / CLI中,将字符串数组转换为本机char **的最有效方法是什么?
我这样做:
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;
// ...
什么,如果有什么需要改进? 从内存管理的角度来看,这样可以吗? 如果需要,我可以更改someNativeFunction
的参数。
谢谢。
除了固定指针在传递给someNativeFunction()
之前超出范围的问题之外,代码可以简化以便更清晰,特别是如果您使用的是MSVC2008或更新版本。 有关如何转换单个字符串的信息,请参阅此页面 (扩展到数组应该是微不足道的)。
编辑:
如果你需要ANSI字符串const char*
那么复制是不可避免的,因为.NET字符串是Unicode(UTF-16)。 在MSVC2008及更高版本上,您的代码可能如下所示:
#include <msclr/marshal.h>
using namespace msclr::interop;
marshal_context context;
array<String^>^ tokenArray = gcnew array<String^> {"TokenONE", "TokenTWO"};
char** tokensAsAnsi = new char* [tokenArray->Length];
for(int i = 0; i < tokenArray->Length; i++)
{
tokensAsAnsi[i] = context.marshal_as<const char*>(tokenArray[i]);
}
int myResult = someNativeFunction(ptr, tokensAsAnsi);
// The marshalled results are freed when context goes out of scope
delete[] tokensAsAnsi; // Please note you must use delete[] here!
这与您的代码示例类似,但不需要指针固定和reinterpret_cast
-ing。
如果你愿意在someNativeFunction()
处理宽字符串const wchar_t*
,你可以直接使用(固定的)内部数据,但是,你必须确保指针保持固定,直到someNativeFunction()
返回,正如指出的那样在评论中,可能会对GC性能产生负面影响。
如果您要编组许多字符串并且性能是最令人担忧的,那么在将所有someNativeFunction()
传递给someNativeFunction()
之前,您可以将编组拆分为多个线程。 在此之前,我建议您分析您的应用程序,看看转换是否确实是一个瓶颈,或者是否更好地将工作重点放在其他地方。
编辑#2:
要获得UTF-8编码的本机字符串,您可以使用修改后的代码版本:
array<String^>^ tokenArray = gcnew array<String^> {"TokenONE", "TokenTWO"};
char** tokensAsUtf8 = new char* [tokenArray->Length];
for(int i = 0; i < tokenArray->Length; i++)
{
array<Byte>^ encodedBytes = Text::Encoding::UTF8->GetBytes(tokenArray[i]);
// Probably just using [0] is fine here
pin_ptr<Byte> pinnedBytes = &encodedBytes[encodedBytes->GetLowerBound(0)];
tokensAsUtf8[i] = new char[encodedBytes->Length + 1];
memcpy(
tokensAsUtf8[i],
reinterpret_cast<char*>(pinnedBytes),
encodedBytes->Length
);
// NULL-terminate the native string
tokensAsUtf8[i][encodedBytes->Length] = '\0';
}
int myResult = someNativeFunction(ptr, tokensAsAnsi);
for(int i = 0; i < tokenArray->Length; i++) delete[] tokensAsUtf8[i];
delete[] tokensAsUtf8;
如果您担心速度,可以为本机字符串预分配一个大缓冲区(如果您知道只有有限的数量)或使用池存储。
编辑#3:(OG Dude)刚刚修正了一些小错字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.