2012-04-28 98 views
1

我想在c#中創建一個類來訪問C++ lib中的函數。函數在C++ dll中:
bool WriteReply(const unsigned char *reply, const unsigned long reply_length)C#包裝類爲c + +的DLL dll

其在C++中如何使用的示例: -

unsigned short msg_id = 0x0000;      
byte msg_body[] = {(byte)(GetTickCount()/0x100)}; // a random value for loopback data 

    // combine the message id and message body into an big msg 
    unsigned long msg_length = sizeof(msg_id)+sizeof(msg_body); 
    byte* big_msg = new byte[msg_length]; 
    big_msg[0] = LOBYTE(msg_id); 
    big_msg[1] = HIBYTE(msg_id); 
    memcpy((void*)&big_msg[2], (void*)msg_body, sizeof(msg_body)); 

    // send the big message 
    if (!big_dev.WriteReply(big_msg, msg_length)) 
    { 
     //do something here 
    } 

我似乎無法從C#的功能傳遞給DLL(AccessViolationException)。這是我試過的命令: -

byte[] bytearray = new byte[3] { 0x01, 0x02, 0x03 }; 
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytearray.Length); 
Marshal.Copy(bytearray, 0, unmanagedPointer, bytearray.Length); 

bool writestatus = (bool)NativeMethods.WriteReply(unmanagedPointer, (uint)bytearray.Length); 

,並在進口方面: -

[DllImport("dllname.dll", EntryPoint = "WriteReply")] 
[return: MarshalAs(UnmanagedType.U1)] 
internal static extern bool WriteReply(IntPtr msg, uint reply_length); 

請讓我知道我在哪裏出了錯謝謝!

+2

你就近了。減去reply_length參數,這是一個uint,而不是一個ulong。 – 2012-04-28 10:04:40

+0

感謝Hans Passant的回覆,但它不起作用。我仍然得到AccessViolationException。還有其他建議嗎?你爲什麼說reply_length是uint,反正不是ulong?謝謝! – csharper 2012-04-29 08:14:49

+2

因爲* long *在C++中是32位的。使用調試器來找出錯誤。 – 2012-04-29 09:20:31

回答

0

假設你的C++方法使用字符串,不會修改它...

試試這個

__declspec(dllexport) bool __cdecl WriteReply(const unsigned char *reply, const unsigned long reply_length); 


[DllImport("libfile.dll", EntryPoint = "WriteReply")] 
private static extern bool WriteReplyExternal(
    [MarshalAs(UnmanagedType.LPStr)] [Out] string replyString, 
    [Out] UInt32 replyLength); 

或者更好(因爲C字符串是空終止,緩衝區是隻讀的,所以你不必擔心緩衝區溢出,長度參數是redudant):

__declspec(dllexport) bool __cdecl WriteReply(const unsigned char *reply); 


[DllImport("libfile.dll", EntryPoint = "WriteReply")] 
private static extern bool WriteReplyExternal(
    [MarshalAs(UnmanagedType.LPStr)] [Out] string replyString); 

這些都將工作,如果該方法不是一個類中,否則您將需要use the C++ mangled name as the entry point

如果您的字符串包含1 ... 127 ASCII範圍以外的字符(例如非英文字母),則應該在編組中使用wchar_t而不是C++和LPWSTR中的字符而不是LPStr。

編輯:

你需要用一個簽名,更適合於.NET例如另一種方法來包裝私有方法

public void WriteReply(string message) 
{ 
    var result = WriteReplyExternal(message, message.Length); 
    if (result == false) 
     throw new ApplicationException("WriteReplay failed ..."); 
} 
+0

嗨丹尼,感謝您的答覆。實際上,函數是c#lib將包含msg的字符串以及其長度傳遞給C++ lib dll的地方。但是,C++ lib dll只接受這些參數:「const unsigned char * reply」以及「const unsigned long reply_length」。我的問題是我不知道如何將字符串和長度從C#傳遞給C++ DLL並接受來自C++ DLL的布爾答覆。有什麼建議嗎?謝謝! – csharper 2012-04-30 01:59:18

+0

查看答案 - 編輯。 – 2012-04-30 09:31:12

+0

嗨,試過這個..didn't太工作..我認爲我已經不通過它作爲一個字節數組的指針,就像它是如何處理在c + +示例代碼(請參閱上文)。你怎麼看?謝謝! – csharper 2012-04-30 09:43:18

0

我認爲,最新加入的代碼提供了一個線索,真正的問題:

if (!big_dev.WriteReply(big_msg, msg_length)) 

這可不行,因爲WriteReply是一個成員函數。您需要調用C風格函數而不是C++成員函數。後者需要一個實例(代碼示例中的big_dev)。

+0

我已經清除了這裏的代碼/問題,並且ReplyMsg/WriteReply其實是這裏的錯字;我已經在這裏糾正它,因爲它是如何在代碼中。我現在要嘗試Danny Varod的建議:) – csharper 2012-05-02 01:11:23

+0

我的答案中的觀點是立場。如果這是一個成員函數,那麼Danny的答案中就沒有任何幫助。即使它不是會員功能,Danny的答案也無濟於事。正如你已經說過的,這不是一個以null結尾的字符串,所以Danny的答案中的所有內容都不適用。嘗試和錯誤不是你在這裏需要的。你需要考慮這個問題。 – 2012-05-02 03:36:25

+0

我不明白你的回覆。 C++示例文件工作正常。當我嘗試從c#訪問.dll時,它不起作用。 – csharper 2012-05-02 07:02:29