2011-07-06 4 views
5

.NETプロジェクト内でアンマネージドC++コードをラッピングしています。このため私はchar*に格納されたUTF8バイトにSystem::Stringを変換する必要があります。.NET 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); 

} 

答えて

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

それとも、文字列(OPの例を含む)は、ほとんどのCの関数のようにゼロ終端が必要な場合、あなたはおそらくゼロバイトを追加する必要があります。

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

非常にいいです、説明をありがとうございます。 –

+1

この例では、 'pinnedBytes'がどのようにゼロターミネータを取得するのか分かりません。これを保証するいくつかの魔法がありますか?それとも読者のための運動として残されているのでしょうか? – StilesCrisis

+1

@StilesCrisis oops、あなたが正しいです、私はOPが自分のcharポインタをprintf%sに渡していたことを見落としているに違いありません。実際には、固定されたバイトの後には通常0バイトが続きますので、とにかく動作しますが、それを保証するルールはわかりません。私は答えを調整します。 – Zarat

関連する問題