【问题标题】:.NET System::String to UTF8-bytes stored in char*.NET System::String 到存储在 char* 中的 UTF8 字节
【发布时间】:2011-09-29 14:07:22
【问题描述】:

我在 .NET 项目中封装了一些非托管 C++ 代码。为此,我需要将System::String 转换为存储在char* 中的UTF8 字节。

我不确定这是否是最好的甚至是正确的方法,如果有人可以查看并提供反馈,我将不胜感激。

谢谢,

/大卫

// Copy into blank VisualStudio C++/CLR command line solution.
#include "stdafx.h"
#include <stdio.h>

using namespace System;
using namespace System::Text;
using namespace System::Runtime::InteropServices;

// Test for calling with char* argument.
void MyTest(const char* buffer)
{
    printf_s("%s\n", buffer);
    return;
}

int main()
{

   // Create a UTF-8 encoding.
   UTF8Encoding^ utf8 = gcnew UTF8Encoding;

   // A Unicode string with two characters outside an 8-bit code range.
   String^ unicodeString = L"This unicode string contains two characters with codes outside an 8-bit code range, Pi (\u03a0) and Sigma (\u03a3).";
   Console::WriteLine(unicodeString);

   // Encode the string.
   array<Byte>^encodedBytes = utf8->GetBytes(unicodeString);

   // Get pointer to unmanaged char array
   int size = Marshal::SizeOf(encodedBytes[0]) * encodedBytes->Length;
   IntPtr pnt = Marshal::AllocHGlobal(size);
   Marshal::Copy(encodedBytes, 0, pnt, encodedBytes->Length);

   // Ugly, but necessary?
   char *charPnt= (char *)pnt.ToPointer();
   MyTest(charPnt);
   Marshal::FreeHGlobal(pnt);

}

【问题讨论】:

    标签: .net c++ string char unmanaged


    【解决方案1】:
    1. 无需创建编码器实例,使用静态实例即可。

    2. 如果被调用的函数不期望指向 HGlobal 堆的指针,您可以对缓冲区使用普通 C/C++ 内存分配(new 或 malloc)。

    3. 在您的示例中,该函数没有所有权,因此您根本不需要副本,只需固定缓冲区即可。

    类似:

    // Encode the text as UTF8
    array<Byte>^ encodedBytes = Encoding::UTF8->GetBytes(unicodeString);
    
    // prevent GC moving the bytes around while this variable is on the stack
    pin_ptr<Byte> pinnedBytes = &encodedBytes[0];
    
    // Call the function, typecast from byte* -> char* is required
    MyTest(reinterpret_cast<char*>(pinnedBytes), encodedBytes->Length);
    

    或者,如果您需要像大多数 C 函数(包括 OP 中的示例)一样以零结尾的字符串,那么您可能应该添加一个零字节。

    // Encode the text as UTF8, making sure the array is zero terminated
    array<Byte>^ encodedBytes = Encoding::UTF8->GetBytes(unicodeString + "\0");
    
    // prevent GC moving the bytes around while this variable is on the stack
    pin_ptr<Byte> pinnedBytes = &encodedBytes[0];
    
    // Call the function, typecast from byte* -> char* is required
    MyTest(reinterpret_cast<char*>(pinnedBytes));
    

    【讨论】:

    • 在这个例子中,我看不出pinnedBytes 会如何得到一个零终止符。有什么魔法可以保证这一点吗?还是留给读者作为练习?
    • @StilesCrisis 哎呀,你是对的,我一定忽略了这样一个事实,即 OP 正在将他的 char 指针传递给 printf %s ,它需要零终止。在实践中,固定字节通常后跟零字节,所以它可能无论如何都可以工作,但我不知道有任何规则可以保证这一点。我会调整答案。
    • 仅供阅读此答案的每个人使用,空字符\0 必须用双引号括起来,例如"\0",否则如果您使用单引号,它最终会变成GetBytes(unicodeString.Concat(0))引用版本GetBytes(unicodeString + '\0')
    猜你喜欢
    • 2012-06-02
    • 1970-01-01
    • 2017-08-25
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 2022-08-12
    • 2020-10-28
    • 1970-01-01
    相关资源
    最近更新 更多