.NET系统::字符串存储在字符UTF8字节*字符串、字节、字符、系统

2023-09-04 00:45:49 作者:余生只缺你

我是一个包装.NET项目里面的一些非托管C ++ code。为此,我需要系统::字符串转换为存储在的char *

UTF8字节

我不能确定这是否是最好的,甚至是正确的方法来做到这一点,我倒是AP preciate如果有人可以看看,并提供反馈。

谢谢

/大卫

  //复制到空白的VisualStudio C ++ / CLR命令行的解决方案。
#包括stdafx.h中
#包括< stdio.h中>

使用命名空间系统;
使用命名空间系统::文本;
使用命名空间系统:运行:: InteropServices;

//测试要求使用char *参数。
无效MyTest的(为const char *缓冲区)
{
    printf_s(%S \ N,缓冲区);
    返回;
}

诠释的main()
{

   //创建一个UTF-8编码。
   UTF8Encoding ^ UTF8 = gcnew UTF8Encoding;

   //一个统一$与外部8位code范围内的两个字符C $ C字符串。
   字符串^ UNI codeSTRING = L这UNI code字符串包含两个字符codeS以外的8位code范围内,PI(\ u03a0)和Sigma(\ u03a3)。;
   控制台:的WriteLine(UNI codeString的);

   // EN code中的字符串。
   阵列<字节> ^ EN codedBytes = utf8->的GetBytes(UNI codeString的);

   //获取指向非托管字符数组
   INT大小= ::元帅一下SizeOf(EN codedBytes [0])* EN codedBytes->长度;
   IntPtr的PNT = ::元帅的AllocHGlobal(大小);
   元帅::复制(EN codedBytes,0,PNT,EN codedBytes->长度);

   //丑陋,但有必要吗?
   字符* charPnt =(字符*)pnt.ToPointer();
   MyTest的(charPnt);
   元帅:FreeHGlobal(PNT);

}
 

解决方案

您并不需要创建一个连接codeR例如,你可以使用静态实例。

Delphi 字符串有多少个字节的函数是什么

如果被调用的函数不指望一个指针HGLOBAL堆,你可以只使用普通的C / C ++内存分配(新的或的malloc)的缓冲区。

在您的例子中,函数没有取得所有权,所以你并不需要一个拷贝所有,只是引脚缓冲区。

是这样的:

  // EN code中的文本作为UTF8
阵列<字节> ^ EN codedBytes =编码:: UTF8->的GetBytes(UNI codeString的);

// prevent GC四处移动字节,而这个变量是在栈上
pin_ptr<字节> pinnedBytes =安培; EN codedBytes [0];

//调用函数,从字节*强制转换 - >字符*是必需的
MyTest的(reinter pret_cast<字符*>(pinnedBytes),EN codedBytes->长度);
 

或者,如果你需要的字符串零结尾最喜欢的C函数(包括在OP的例子),那么你或许应该加上一个零字节。

  // EN code中的文本为UTF8,确保数组是零结束
阵列<字节> ^ EN codedBytes =编码:: UTF8->的GetBytes(UNI $ C $的CString +\ 0);

// prevent GC四处移动字节,而这个变量是在栈上
pin_ptr<字节> pinnedBytes =安培; EN codedBytes [0];

//调用函数,从字节*强制转换 - >字符*是必需的
MyTest的(reinter pret_cast<字符*>(pinnedBytes));
 

I am wrapping some unmanaged C++ code inside a .NET project. For this I need to convert System::String to UTF8-bytes stored in char*.

I am unsure if this is the best or even a correct way to do this and I'd appreciate if someone could take a look and provide feedback.

Thanks,

/David

// 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);

}

解决方案

You don't need to create an encoder instance, you can use the static instances.

If the called function doesn't expect a pointer to the HGlobal heap you can just use plain C/C++ memory allocation (new or malloc) for the buffer.

In your example the function doesn't take ownership so you don't need a copy at all, just pin the buffer.

Something like:

// 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);

Or if you need the string zero-terminated like most C functions (including the example in the OP) then you should probably add a zero byte.

// 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));