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.其他类型实在不清楚就查一下,各种转换文章很多,当然不一定全对,要多尝试