2011-04-14 2 views
2

나는 C++과 C# 통신이 관련된 here 질문을했다. 문제는 해결되었지만 새로운 문제가 발생했습니다. 이 문자열을 반환어떻게 'System :: String ^'을 'TCHAR'로 변환하나요?

(C#을)

return Marshal.PtrToStringAnsi(decryptsn(InpData)); 

이는 TCHAR * 예상 (C + +를)

lpAlpha2[0] = Company::Pins::Bank::Decryption::Decrypt::Decryption("123456"); 

나는이 문제를 해결하는 방법을 검색 좀했지만, 내가 왜 확실하지 않다 문자열에는 당근 (^)이 있습니다. String에서 C++이 받아 들일만한 다른 것으로 리턴 값을 변경하는 것이 가장 좋을까요? 또는 값을 할당하기 전에 변환을 수행해야합니까?

+1

re : 귀하의 깃발 - 당신이 이메일로 팀 @ stackoverflow 그 도움이 필요합니다. 또한, 교훈을 배웠습니까? – Will

답변

2
질문을 할 수있는 정말 두서 방법이지만, 당신이 char *String ^를 변환하는 방법을 의미하는 경우, 당신은, 하위, 이전에 사용 된 것과 동일한 마샬 러를 사용

:

char* unmanagedstring = (char *) Marshal::StringToHGlobalAnsi(managedstring).ToPointer(); 

편집 : Marshal::FreeHGlobal을 사용하여 완료되면 할당 된 메모리를 해제하는 것을 잊지 마십시오.

+0

'HGLOBAL'은'char *'이 아니기 때문에 캐스팅해서는 안됩니다. 'HGLOBAL'에서 포인터를 가져 오려면'GlobalLock'을 사용하십시오. 더 나아가 'HGLOBAL'을 완전히 피하십시오. –

4

구문 String^은 "(가비지 수집 된) System.String 참조"에 대한 C++/CLI 대화입니다.

String을 C 문자열로 변환하는 두 가지 옵션이 있습니다. 이는 TCHAR*을 표현하는 또 다른 방법입니다. C++에서 선호하는 방법은 변환 된 문자열을 유니 코드 또는 MBCS 프로젝트로 프로젝트를 빌드하는 데 따라 std::wstring 또는 std::string의 C++ 문자열 유형으로 저장하는 것입니다. 이 같은 것을 사용할 수 있습니다 경우

:

std::wstring tmp = msclr::interop::marshal_as<std::wstring>(/* Your .NET String */); 

또는

올바른 넓거나 좁은 문자열 형식으로 문자열을 변환하면
std::string tmp = msclr::interop::marshal_as<std::string>(...); 

, 당신은 다음에 액세스 할 수 있습니다 그것 다음과 같이를 입력하면 C 문자열 표현이 가능합니다.

callCFunction(tmp.c_str()); 

callCFunction은 C 스타일 char* 또는 wchar_t* (이 경우 TCHAR*은 컴파일 설정에 따라 "성능 저하"가 발생할 것으로 예상 함)를 가정합니다.

+0

이 두 표준은 wstring 또는 string이 std의 멤버가 아니라고 말합니다. 종류의 참조가 누락 되었습니까? – Andy

+0

C++ 코드에서'#include '을 선언해야합니다. –

4

String은 ^이므로 관리되는 참조 용 마커입니다. 기본적으로 객체 유형을 가리킬 수 있고 다른 포인터 유형을 가리키거나 무효화 할 수 있다는 점을 제외하면 관리되지 않는 영역에서는 *과 같은 방식으로 사용됩니다.

TCHAR는 #define에 의해 정의 (혹은, 내가 기억할 수없는 typedefed)를 _UNICODE 전 처리기 정의에 따라, char 또는 wchar_t 중 하나입니다. 따라서, 나는 그것을 사용하여 코드를 두 번 작성합니다.

어느 인라인 :

TCHAR* str; 
String^ managedString 
#ifdef _UNICODE 
str = (TCHAR*) Marshal::StringToHGlobalUni(managedString).ToPointer(); 
#else 
str = (TCHAR*) Marshal::StringToHGlobalAnsi(managedString).ToPointer(); 
#endif 

// use str. 

Marshal::FreeHGlobal(IntPtr(str)); 

또는 출력 버퍼가 이미 할당 충분히 큰되었다고 가정 둘 변환 방법의 한 쌍

. 메소드 오버로딩은 TCHAR의 정의에 따라 올바른 것을 선택하도록해야합니다.

void ConvertManagedString(String^ managedString, char* outString) 
{ 
    char* str; 
    str = (char*) Marshal::StringToHGlobalAnsi(managedString).ToPointer();  
    strcpy(outString, str);  
    Marshal::FreeHGlobal(IntPtr(str)); 
} 

void ConvertManagedString(String^ managedString, wchar_t* outString) 
{ 
    wchar_t* str; 
    str = (wchar_t*) Marshal::StringToHGlobalUni(managedString).ToPointer();  
    wcscpy(outString, str);  
    Marshal::FreeHGlobal(IntPtr(str)); 
} 
+0

Blindy와 같은 문제 인'HGLOBAL'은 내용에 대한 포인터를 얻기 위해'GlobalLock'에 전달되어야하는 불투명 한 구조입니다. –

+0

그렇다면 Microsoft의 설명서가 잘못되었습니다. http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.stringtohglobalansi.aspx –

+0

Ok, ['GlobalLock'] (http://msdn.microsoft.com/en-us/ 라이브러리/aa366584.aspx)는'MEM_FIXED'가'GlobalAlloc'에 전달되면 no-op입니다. 그러나 MSDN은'StringToHGlobalAnsi'가 내부적으로 사용하는 플래그를 말하지 않습니다. 예를 들어 사양에 포함 된 것처럼 의지하는 것은 악명 높은 아이디어입니다. –

관련 문제