我现在需要调用一个设备的sdk,里面有个函数用了回调函数,我查了些资料,也用了委托,可能我写错了,
不知道如何才能取得函数返回的数据。
函数如下:
int __stdcall tltmStartReadingItems(HANDLE hHandle, unsigned int uiFieldsMask, BOOL boSetEAS,
void (__stdcall *lpfnRawCallBack)(HANDLE hHandle, int iReasonForCall, struct tltmRawItem *myRawItem, void *pParam),
void (__stdcall *lpfnCallBack)(HANDLE hHandle, int iReasonForCall, struct tltmItem *myItem, void *pParam), void *pParam)哪位大哥指点一下小弟,谢谢!
不知道如何才能取得函数返回的数据。
函数如下:
int __stdcall tltmStartReadingItems(HANDLE hHandle, unsigned int uiFieldsMask, BOOL boSetEAS,
void (__stdcall *lpfnRawCallBack)(HANDLE hHandle, int iReasonForCall, struct tltmRawItem *myRawItem, void *pParam),
void (__stdcall *lpfnCallBack)(HANDLE hHandle, int iReasonForCall, struct tltmItem *myItem, void *pParam), void *pParam)哪位大哥指点一下小弟,谢谢!
比如SDK中有个查找所有窗口的函数:
[DllImport("user32")]
private static extern bool EnumWindows(DelegateEnumWindow ew, int lParam);
上面的参数ew就是一个委托(回调函数),再看这个参数的声明:
delegate bool DelegateEnumWindow(IntPtr hWnd, int lParam);再看调用:
DelegateEnumWindow dew = new DelegateEnumWindow(CallBackProc);//实例化委托
EnumWindows(dew, 0);//调用API再看CallBacProc的定义:
private bool CallBackProc(IntPtr hWnd, int lParam)
{
//在这里实现自己的查找逻辑,比如窗口的类名为XXXXX.
StringBuilder sb = new StringBuilder(256);
GetWindowText(hWnd, sb, sb.Capacity);
if(sb.ToString() == "XXX")
{
Console.WriteLine(" 找到了"); return true;
}
return false;
}CallBackProc函数是由系统自动调用(调用者是EnumWindows函数),而不是由程序员调用
我的sdk里面有2个函数作为参数1)void (__stdcall *lpfnRawCallBack)(HANDLE hHandle, int iReasonForCall, struct tltmRawItem *myRawItem, void *pParam)2)void (__stdcall *lpfnCallBack)(HANDLE hHandle, int iReasonForCall, struct tltmItem *myItem, void *pParam)如何实现对这2个函数的调用啊?
第一个是Ptr,第二个是整数,都没问题,关键是第三个是一个结构指针,要先定义结构(和C++里定义的一样),再跨平台申请内存,以这块内存的地址作为参数,最后一个是一个Void类型的指针,具体指向什么数据类型也要查看C++的定义,建议楼主查看设备开发手册说明,或者到该设备官网了解那个结构和Void指针的详细情况,否则调用一定失败
估计我的错误应该在Void类型的指针上面,
C++的示例代码里面是这样写的tltmStartReadingItems(m_hHandle, uiFields, boSetEAS, myRawCallback, myCallback, this);void __stdcall myRawCallback(HANDLE hHandle, int iReasonForCall, tltmRawItem *myItem, void *pParam)
{
。
}void __stdcall myCallback(HANDLE hHandle, int iReasonForCall, tltmItem *myItem, void *pParam)
{
。
}在C#里面我应该用什么指针来代替c++的this呢?
我用了以后,报ArgumentNullException的错误。
2. delegate的参数声明一定要跟c的一致。回调是可以执行的,跟普通的函数调用一样方便可靠。
public delegate void lpfnRawCallBack(IntPtr hHandle, int iReasonForCall,ref tltmRawItem myRawItem, IntPtr pParam);public delegate void lpfnCallBack(IntPtr hHandle, int iReasonForCall, ref tltmItem myItem, IntPtr pParam);//lpfnRawCallBack用
public static void myRawCallBack(IntPtr hHandle, int iReasonForCall, ref Tagsys.tltmRawItem myRawItem, IntPtr pParam)
{
。
}//lpfnCallBack用
public static void myCallBack(IntPtr hHandle, int iReasonForCall, ref Tagsys.tltmItem myRawItem, IntPtr pParam)
{
。。
}//实际调用
lpfnRawCallBack rawBk = new lpfnRawCallBack(CLASS1.myRawCallBack);lpfnCallBack myBk = new lpfnCallBack(CLASS1.myCallBack);intErr = tltmStartReadingRawItems(this.m_handle, 1, 0,rawBk, IntPtr.Zero);
intErr = tltmStartReadingItems(this.m_handle, 1, 0, rawBk, myBk, IntPtr.Zero);debug的时候,这两个函数都没有进去,抛ArgumentNullException的异常,请问这是什么原因呢?
示例代码只有c++,里面的void *pParam用的是this,那么我在.net里面应该用什么呢?
请高手指点一下
IntPtr pParam = gh.AddrOfPinnedObject();
intErr = tltmStartReadingRawItems(this.m_handle, 1, 0, rawBk, pParam);
gh.Free();这样试试看能成功否获取到this的指针
public static void myCallBack(IntPtr hHandle, int iReasonForCall, ref Tagsys.tltmItem myRawItem, IntPtr pParam)
抛下面的异常:
System.ArgumentException:Object 包含非基元或非直接复制到本机结构中的数据看来只有通过别的方法取得当前实例的内存地址了。
不能回调的话就郁闷了
this代表的是classC++的示例代码里面是这样写的tltmStartReadingItems(m_hHandle, uiFields, boSetEAS, myRawCallback, myCallback, this);void __stdcall myRawCallback(HANDLE hHandle, int iReasonForCall, tltmRawItem *myItem, void *pParam)
{
。
}void __stdcall myCallback(HANDLE hHandle, int iReasonForCall, tltmItem *myItem, void *pParam)
{
。
}
//回调函数
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void lpfnRawCallBack(IntPtr hHandle, Int16 iReasonForCall, ref Tagsys.tltmRawItem myRawItem, TAGSYSLP101 pParam); public class Tagsys
{
//// Raw Reading
//int __stdcall tltmStartReadingRawItems(HANDLE hHandle, unsigned int uiFieldsMask, BOOL boSetEAS, void (__stdcall *lpfnRawCallBack)(HANDLE hHandle, int iReasonForCall, struct tltmRawItem *myRawItem, void *pParam), void *pParam);
[DllImport(ReaderList.READERS_TAGSYS_DLL, EntryPoint = "tltmStartReadingRawItems", CharSet=CharSet.Ansi, ExactSpelling=false,CallingConvention=CallingConvention.StdCall)]
public static extern int tltmStartReadingRawItems(IntPtr hHandle, uint uiFieldsMask, Boolean boSetEAS,lpfnRawCallBack lpfnRawCallBack, TAGSYSLP101 pParam);}//实际应用:
public unsafe class TAGSYSLP101 : AbstractReader
{
public TAGSYSLP101()
{
lpfnRawCallBack myRawCallBk = new lpfnRawCallBack(TAGSYSLP101.myRawCallBack);intErr = Tagsys.tltmStartReadingRawItems(this.m_device_handle, Tagsys.TLTM_ITEM_ALL, false, myRawCallBk, this);}public static void myRawCallBack(IntPtr hHandle, Int16 iReasonForCall, ref Tagsys.tltmRawItem myRawItem, TAGSYSLP101 pParam)
{
Console.WriteLine("here myRawCallBack");
}
}麻烦帮我看看对不对。另外,回调函数当中有数据结构作为参数,在回调的时候,会不会因为没有提前实例化而出错呢?
public static void myRawCallBack(IntPtr hHandle, Int16 iReasonForCall, ref Tagsys.tltmRawItem myRawItem, TAGSYSLP101 pParam)
把数据结构改成类会不会好一些?
public delegate bool CallBack(int hwnd, int lParam);