查看文章 |
c#导出C++回调函数
2008年10月18日 星期六 01:11
c#导出C++回调函数(cici) 最近在公司做一个新的项目,由于C#做界面是非常快速的,于是决定用C#重写C++的界面,而原来的C++动态链接库是不需要修改的。只需要调用一下就可以了。
在调用过程中发现C++有回调函数,于是翻开MSDN终于发现,回调函数是使用委托来调用。 比如: 在C++中的回调函数是这样定义的: typedef void (*CiCiCallBack) (bool started, void* client,char *message); 导出函数这样定义: extern "C" _declspec(dllexport) bool Test(char* fileName, CiCiCallBack callback) { int n =10000; MessageBoxExA(NULL,fileName,NULL,NULL,NULL); callback(TRUE,&n, strcat(fileName, " hello world")); return TRUE; } 于是在C#中可以这样写: public delegate void CiCiCallBack(bool started, IntPtr client,string msg); [DllImport("CppCallBackDll.dll", EntryPoint = "Test", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)] public static extern bool Test(string fileName, [In] CiCiCallBack callback); 在调用的时候这样调用: CiCiCallBack callbackDelegate = new CiCiCallBack (CallBack); Test(Application.ExecutablePath, callbackDelegate); 当然还得定义一个回调函数: private void CallBack(bool flag, IntPtr client, string msg) { MessageBox.Show(msg, "", MessageBoxButtons.OK, MessageBoxIcon.Information); } 理论上当执行到Test(Application.ExecutablePath, callbackDelegate);时候会自动调用回调函数。 但是实际却报出了这个错误: Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. ![]() 熟悉C++ 编程的人应该知道这个错误一般是由以下两种情况产生的: 1、参数传递有错误,尤其是指针传递的时候。 2、函数部分地方的约定不统一(压栈方式可能不统一)。 本文就是第二个原因,不难发现CPP中回调函数的约定和导出函数的约定是不统一的。于是强制在CPP代码中将回调函数定义为: typedef void (_stdcall *CiCiCallBack) (bool started, void* client,char *message); 将导出函数修改为: extern "C" _declspec(dllexport) bool _stdcall Test(char* fileName, CiCiCallBack callback) 对了,就是加了一个_stdcall得约定条件。_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式。 最后附上源代码。点击此处 |
最近读者:
