標籤:int oid sp1 str 查看 [] ack imp att
最近完成了一個C++版本的對外sdk程式,其中有部分回呼函數使用。
C++程式使用時沒有異常,但是在C#環境下使用時出了點問題,簡單總結下。
感謝部落格:http://blog.csdn.net/songjinshi/article/details/8153635 協助我解決了問題。
C++中的回呼函數原型如下:
typedef void (STDCALL *fCallback)(const char* csDetail, void *pUser);
其中有一個參數是char * ,就是字元指標,這裡需要特別注意。
在C#中需要以委託完成相應回調操作,心路曆程如下:
1,開始使用如下形式的委託函數:
public delegate void MSGCALLBACK(ref byte pBuffer, UIntPtr pUser);
出現問題,回呼函數僅能接收到一個字元,而非整個字元數組的值。
2,使用如下形式的委託函數:
public delegate void MSGCALLBACK(ref byte[] pBuffer, UIntPtr pUser);
出現如1 的問題,回呼函數僅能接收到一個字元,而非整個字元數組的值。
3,使用string代替byte數組,委託函數如下:
public delegate void MSGCALLBACK(string pBuffer, UIntPtr pUser);
正常情況下接收資料均正常,但是在接收中文字元“面”是,出現異常,查看記憶體整個記憶體位址位置的值都異常了,如下:
,亂碼問題是一個“面”子,相應xml格式中的“<”也不存在了,導致解析xml異常,
相應記憶體位址內容如下:
2f表示字元“/” 45是表示“E”,可以看到記憶體位址“/”前面的資訊已經面目全非了,
這裡具體什麼原因確實沒有找到,希望有大神可以幫忙解答。
4,最終正確的委託函數如下:
需要包含包 “using System.Runtime.InteropServices;
public delegate void MSGCALLBACK([MarshalAs(UnmanagedType.LPArray, SizeConst = 8000)]byte[] pBuffer, UIntPtr pUser);
成功的接收回調訊息並完成訊息解析,沒有出現任何異常。
解釋如下:
在給c++傳入數組參數時,必須得用 [MarshalAs(UnmanagedType.LPArray,SizeConst=8000)] 處理一下,相當於是告訴c++,c#傳入的是一個長度為8000的數群組類型,如果不寫這句話的話,你回呼函數接收到的參數將只有一條資料。
對於MarshalAs,MarshalAs屬性指示如何在Managed 程式碼和Unmanaged 程式碼之間封送資料。
當 MarshalAsAttribute.Value 設定為 LPArray時,必須設定 SizeConst 以指示數組中的元素數。當需要區分字串類型時,ArraySubType 欄位可以選擇包含數組元素的 UnmanagedType。此 UnmanagedType 只可用於作為結構中的欄位的數組。而SizeConst則是指數組中的元素個數。
轉載一個連結,用以協助理解MarshalAs如何使用:
http://blog.csdn.net/xiaobai1593/article/details/7025775
c#調用c++帶有回呼函數方法的實現