2011-07-06 1 views
5

.NET 프로젝트 내에 관리되지 않는 C++ 코드를 래핑합니다. 이를 위해 System::Stringchar*에 저장된 UTF8 바이트로 변환해야합니다..NET System :: 문자열을 char로 저장된 UTF8-bytes에 저장합니다.

이것이 최선이거나 올바른 방법인지 확신 할 수 없으며 누군가가 살펴보고 의견을 제시 할 수 있다면 감사하겠습니다.

감사합니다,

/데이비드

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

또는 문자열 (영업의 예 포함) 대부분의 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'가 어떻게 0 종결자를 얻는 지 보지 못합니다. 이것을 보장하는 마술이 있습니까? 아니면 독자를위한 운동으로 남았습니까? – StilesCrisis

+1

@StilesCrisis oops, 네 말이 맞아, 나는 OP가 자신의 char 포인터를 printf % s에 전달했음을 간과 했음에 틀림 없다. 실제로 고정 된 바이트 뒤에 0 바이트가옵니다. 따라서 어쨌든 작동 할 수 있습니다. 그러나이를 보장하는 규칙을 알지 못합니다. 나는 대답을 조정할 것이다. – Zarat

관련 문제