2011-04-14 91 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"); 

我GOOGLE瞭如何解決這個問題,但我不知道爲什麼字符串上有一個胡蘿蔔(^)。最好是將String的返回值改爲C++可以接受的其他值嗎?或者我需要在分配值之前進行轉換?

+1

re:你的國旗 - 你需要發郵件給team @ stackoverflow尋求幫助。另外,經驗教訓? – Will 2011-04-15 13:11:53

回答

2

這是一個非常散漫的方式來問這個問題,但如果你的意思是如何將String ^轉換爲char *,那麼你用你之前所使用的相同編組,只有向後:

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

編輯:不要忘記在使用Marshal::FreeHGlobal時釋放分配的內存。

+0

'HGLOBAL'不是'char *',不應該轉換爲一個。爲了讓指針脫離「HGLOBAL」,使用'GlobalLock'。更好的是,完全避免'HGLOBAL'。 – 2011-04-15 23:14:38

4

語法String^是C++/CLI針對「(垃圾回收)引用System.String」的說法。

對於將String轉換爲C字符串,您有幾個選項,這是表示TCHAR*的另一種方式。在C++中,我的首選方法是將轉換的字符串存儲爲C++字符串類型,即std::wstringstd::string,具體取決於將項目構建爲Unicode還是MBCS項目。

在這兩種情況下,你可以使用這樣的事情:

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

std::string tmp = msclr::interop::marshal_as<std::string>(...); 

一旦你轉換的字符串到正確的寬或窄字符串格式,你就可以訪問它的C字符串表示使用c_str()函數,如下所示:

callCFunction(tmp.c_str()); 

假設callCFunction希望您通過它C風格char*wchar_t*(其中TCHAR*將「降級」,具體取決於您的編譯設置。

+0

這兩個標準都表示wstring或string不是std的成員。我是否缺少類型的參考? – Andy 2011-04-14 17:43:15

+0

您需要在您的C++代碼中包含'#include '才能獲得聲明。 – 2011-04-14 18:31:29

4

字符串有一個^,因爲這是管理參考的標記。基本上,它的使用方式與非託管土地上的*相同,除了它只能指向一個對象類型,而不是指向其他指針類型或無效。

TCHAR已經#defined(或者通過typedef,我記不清了)要麼charwchar_t的基礎上,_UNICODE預處理器定義。因此,我會使用它並編寫兩次代碼。

內聯:

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's是不透明的結構,它應該被傳遞給'GlobalLock'以獲得指向內容的指針。 – 2011-04-15 23:19:22

+0

如果是這樣,那麼微軟的文檔是錯誤的。 http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.stringtohglobalansi.aspx – 2011-04-15 23:33:41

+0

好的,['GlobalLock'](http://msdn.microsoft.com/en-us/ library/aa366584.aspx)如果'MEM_FIXED'被傳遞給'GlobalAlloc',則它是一個空操作。但是MSDN並沒有說內部使用了什麼標誌'StringToHGlobalAnsi'。依靠例子,如果他們是規範的一部分是一個臭名昭着的壞主意。 – 2011-04-15 23:52:44

相關問題