2013-03-07 14 views
8

功能在C DLL看起來是這樣的:PInvoke C *中的char *在C#中作爲字符串處理。發行與空字符

int my_Funct(char* input, char* output); 

我必須從C#應用程序調用此。我這樣做的方式如下:

...DllImport stuff... 
public static extern int my_Funct(string input, string output); 

輸入字符串完美傳輸到DLL(我有可見的證據)。函數填充的輸出雖然是錯誤的。我在這六數據,如:

3F-D9-00-01 

但不幸的一切,這是兩個零被切斷後,只有前兩個字節來我的C#應用​​程序。它發生,因爲(我猜)它視爲空字符並將其作爲字符串的結尾。

任何想法我怎麼能擺脫它?我試圖將它指定爲IntPtr而不是字符串,但我不知道該如何處理它。 我試圖做後:

byte[] b1 = new byte[2]; 
Marshal.Copy(output,b1,0,2); 

2應該是正常的字節數組的長度。但是我會遇到各種各樣的錯誤:比如「請求的範圍超出了數組的末尾」。或「嘗試讀取或寫入受保護的內存......」

我欣賞任何幫助。

+0

(1)C#字符串比字符寬;它們的寬度是2個字符而不是1.(2)此函數返回的char *不會具有必需的附加結構以成爲有效的C#字符串(即使它的寬度正確)。 – 2013-03-07 14:41:52

+0

您需要閱讀COM Interop和P/Invoke以瞭解如何執行此操作。做到這一點,並回答您對該材料的任何問題。 – 2013-03-07 14:43:50

+0

pinvoke編組僅支持C字符串。當它具有0之後的字節時,它顯然不是C字符串。它是一個字節[]。但是,如果發生嚴重的掛斷問題,則沒有人能夠確定*很多*字節的相關性。這個函數在C代碼中也很難使用,當你編譯它的時候並沒有什麼好處。你最好修復它。如果長度可預測,請使用MarshalAs.SizeConst。 – 2013-03-07 16:04:27

回答

12

您錯誤地編組輸出字符串。將數據從託管傳遞到本地時,在p/invoke聲明中使用string是適當的。但是當數據流向另一個方向時,你不能使用它。相反,您需要使用StringBuilder。就像這樣:

[DllImport(...)] 
public static extern int my_Funct(string input, StringBuilder output); 

然後分配的內存輸出:

StringBuilder output = new StringBuilder(256); 
//256 is the capacity in characters - only you know how large a buffer is needed 

然後你就可以調用該函數。

int retval = my_Funct(inputStr, output); 
string outputStr = output.ToString(); 

在另一方面,如果這些參數在他們的空字符,那麼你不能編組爲字符串。這是因爲編組人員不會編組任何超過空值的東西。相反,您需要將其編組爲字節數組。

public static extern int my_Funct(
    [In] byte[] input, 
    [Out] byte[] output 
); 

符合您的C聲明。

然後假設ANSI編碼您輸入的字符串轉換爲字節數組是這樣的:

byte[] input = Encoding.Default.GetBytes(inputString); 

如果要使用不同的編碼,這是明顯如何做到這一點。對於輸出你需要分配數組。假設它是相同的長度,你可以這樣做輸入:

byte[] output = new byte[input.Length]; 

不知怎麼你的C函數才知道數組的長度。我會留給你的!

然後你就可以調用函數

int retval = my_Funct(input, output); 

然後到輸出數組轉換回再次使用Encoding類C#字符串。

string outputString = Encoding.Default.GetString(output); 
+0

非常感謝! [Out]字節[] ...版本正常工作! – user2124150 2013-03-08 07:45:12