c++ /CLI字符串数组到本地c++字符的转换
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;
// ...
有什么需要改进的地方吗?从内存管理的角度来看,这是ok的吗?如果需要,我可以更改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()
之前,将封送分配给多个线程。在此之前,我建议对您的应用程序进行分析,看看转换是否真的是一个瓶颈,或者将精力集中在其他地方是否更好。
编辑# 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] = ' ';
}
int myResult = someNativeFunction(ptr, tokensAsAnsi);
for(int i = 0; i < tokenArray->Length; i++) delete[] tokensAsUtf8[i];
delete[] tokensAsUtf8;
如果你关心速度,你可以为本地字符串预先分配一个大的缓冲区(如果你知道只有有限的数量),或者使用池存储。
编辑#3:(OG Dude)只是修正了一些小的打字错误。
- C++字符*缓冲区的大小
- HEX值到wchar_t字符(UTF-8)的转换
- 为什么 Serial.println(<char[]>);返回随机字符?
- 我的字符计数代码计算错误.为什么
- 字符串-C++后显示的随机字符
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 如何在C++中从字符串中分割字符
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 指向指向字符数组的指针数组的指针
- 如何用转义符替换字符串中的所有特殊字符
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 比较字符数组
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 如何在C++中确定文本文件中的元素是字符还是数字
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++中无符号字符溢出
- 使用无符号字符数组有效存储内存