2010-05-08 98 views
1

C代碼傳遞C字符串參考C#

extern "C" __declspec(dllexport) int export(LPCTSTR inputFile, string &msg) 
{ 
    msg = "haha" 
} 

C#代碼

[DllImport("libXmlEncDll.dll")] 
public static extern int XmlDecrypt(StringBuilder inputFile, ref Stringbuilder newMsg) 
} 

,當我嘗試檢索newMsg的內容說,我試圖寫一個我得到了一個錯誤保護存儲區。

什麼是從c到c#檢索字符串的最佳方法。謝謝。

回答

4

使用帶有以C++類作爲參數的導出的DLL即使在C++中也是危險的。與C#互操作是不可能的。你不能使用相同的內存分配器,你不能調用構造函數和析構函數。更不用說你的C++代碼是無效的,它實際上並不返回字符串。

改爲使用C字符串。使它看起來像這樣:

extern "C" __declspec(dllexport) 
void __stdcall XmlDecrypt(const wchar_t* inputFile, wchar_t* msg, int msgLen) 
{ 
    wcscpy_s(msg, msgLen, L"haha"); 
} 

[DllImport("libXmlEncDll.dll", CharSet = CharSet.Auto)] 
public static extern void XmlDecrypt(string inputFile, StringBuilder msg, int msgLen) 
... 
    StringBuilder msg = new StringBuilder(666); 
    XmlDecrypt(someFile, msg, msg.Capacity); 
    string decryptedText = msg.ToString(); 

的一些注意事項與這些代碼片段:

  • 的__stdcall說明符用於選擇DLL出口標準調用約定,這樣你就不必在[DllImport]屬性中使用CallingConvention屬性。
  • C++代碼使用wchar_t,適合存儲Unicode字符串。這樣可以防止從XML文件獲取的文本轉換爲8位字符(即有損轉換)時丟失數據。
  • 選擇合適的msgLen參數對於保持此代碼的可靠性非常重要。不要忽略它,如果它溢出了「msg」緩衝區,C++代碼將銷燬垃圾收集堆。
  • 如果你確實需要使用std :: string,那麼你需要用C++/CLI語言編寫一個ref類包裝器,以便它可以從System.String轉換爲std :: string。
0

漢斯,

它的工作原理,非常感謝。順便說一下,我在C#代碼中發現了一個問題。字符串inputFile只傳遞第一個字符。我通過編組進行了修改

[DllImport("libXmlEncDll.dll")] 
public static extern void test(string file, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder msg, int msgLen); 

再次,謝謝。

+0

這是因爲您忘記了[DllImport]屬性中的CharSet屬性。請注意我是如何使用CharSet.Auto的,這會讓您獲得所需的行爲。 – 2010-05-10 16:59:37