1.回調函數的使用
c++的回調函數如下所示:
typedef void (CALLBACK *Data)(long lHandle, DATA_TYPE eDataType, unsigned char *pBuffer, unsigned long lBufSize, void *pUserData)
調用回調函數的函數如下所示:
SDK_API long STDCALL StartData(long lID, S_DATA_INFO *pDataInfo, Data fData, Void *pUserData = NULL)
C#里對應的就是使用委托了。
回調函數對應的委托聲明:
CallingConvention.StdCall還是很有用的。
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)] public delegate void Data(int lHandle, DATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, IntPtr pUserData);
調用委托的函數:
[DllImport("SDK.dll")] public extern static int StartData(int lID, ref DATA_INFO pDataInfo, Data fRealData, IntPtr pUserData);
使用方法:
首先聲明一個全局變量myData,如果是函數里臨時聲明的變量可能在函數執行結束時就被垃圾回收了,后面的自然無法執行了。
SDK.Data myData;
使用時給它初始化
myCBRealData = new IPCSDK.CBRealData(DoData);
然后調用執行函數
int lData = SDK.StartData(ID, ref dataInfo, myData, IntPtr.Zero);
最后DoData函數里執行回調函數該做的事
public void DoData(int lHandle, SDK.DATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, IntPtr pUserData)
{
....
}
2.struct 結構體大小的設置
C++很簡單,數組可以直接定義長度
typedef struct tagInfo
{
unsigned char ucSoftWareVersion[4];//軟件版本
}S_INFO;
C#:
要使用[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public struct S_INFO
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] ucSoftWareVersion;//軟件版本
};
3.const char * 等這一類的轉換
char * 一般直接用string就好了,
const char *一般要 StringBuilder
出現錯誤就多試試了
其他信息: 對 PInvoke 函數“SDK::Open”的調用導致堆棧不對稱。原因可能是托管的 PInvoke 簽名與非托管的目標簽名不匹配。請檢查 PInvoke 簽名的調用約定和參數與非托管的目標簽名是否匹配。
這個錯誤網上不少說是要在函數上面加CallingConvention.StdCall
[DllImport("SDK.dll", CallingConvention= CallingConvention.StdCall, CharSet= CharSet.Ansi)]
試了沒用,最后發現是const char *要 StringBuilder,用string、intptr都沒用
4.C++的long一般是4個字節對應C#的int
5.指針類型一般用intptr,然后再讀出來
6.其他類型實在不清楚就查一下,各種轉換文章很多,當然不一定全對,要多嘗試