这几天做项目时,遇到了C#调用C++函数指针的问题,C#调用C++ dll中的函数很简单,函数指针还真没调过,看了几篇文章研究了会儿后把问题搞定了,这里总结一下。 先看两篇文章: http://jc./n/200607/14/n20060714_19510.shtml C#中的函数指针(实在是找不到出处了) http://dev.csdn.net/article/69/69261.shtm 如何在C#中使用 Win32和其他库(这篇我在msdn上找了半天也没找到!) 函数指针搞C++的人应该都知道,效率高,易用性强,隐蔽代码等。在C++里面调用C++写的dll的函数指针那是在容易不过了。使用C#就稍微麻烦点了!那怎么掉呢?通过上面的第一篇文章我们知道应该使用委托 delegate。如果再高级点,定义一个函数指针结构(有点像linux的内核),也同样可以用C#调用。 猴子提示:委托就和C++中的函数指针一样。 下面我只写出了.h和.cs文件,都是伪代码,大家如果能明白意思,可以很简单的用到自己的项目了。 .h文件 // 获得梦之都网站的ip//// pDes - 梦之都的网址 http://www./// 返回值 - false 获取失败 true 获取成功typedef bool (*Dreamdu_PGetIP)(char const* pDes) ; // 获得可爱的猴子的名字//// pDes - 可爱的猴子的名字 http://www./blog/// 返回值 - false 获取失败 true 获取成功typedef void (*Monkey_PGetName)(char const* pDes) ; // 梦之都的函数指针结构struct Dreamdu_Struct{ Dreamdu_PGetIP Dreamdu_GetIP; Monkey_PGetName Monkey_GetName;} ;// 获取梦之都的函数指针结构的函数指针// pDreamdu - 梦之都的函数指针结构数组typedef void (*Dreamdu_PGetDreamduStruct)(Dreamdu_Struct *pDreamdu) ;// 获取梦之都函数指针结构的函数 这个就是输出函数啦 哈哈// pDreamdu - 函数指针结构数组extern "C" Dreamdu_DLL_EXT_ void Dreamdu_GetDreamduStruct(Dreamdu_Struct *pDreamdu) ; .csCS文件 public class Dreamdu{ //加载dll [DllImport("kernel32.dll")] private static extern IntPtr LoadLibrary(string lpFileName); //获得函数指针的地址 [DllImport("kernel32.dll")] private static extern GetDreamduFuns GetDreamduAddress(IntPtr hModule, string lpProcName); //释放dll [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)] private static extern bool FreeLibrary(IntPtr hModule); private delegate void GetDreamduFuns(IntPtr funs); private delegate bool Dreamdu_PGetIP(string name); private delegate void Monkey_PGetName(string name); //函数指针结构在cs中的声明 [StructLayout(LayoutKind.Sequential, Pack = 1)] private class Dreamdu_Struct { public Dreamdu_PGetIP GetIP; public Monkey_PGetName GetName; } //装载 Dll public static void LoadDll(string lpFileName) { hModule = LoadLibrary(lpFileName); if (hModule == IntPtr.Zero) throw (new Exception()); } //获得函数指针 public static void LoadFun(string lpProcName) { if (hModule == IntPtr.Zero) throw (new Exception("")); dreamduStruct = GetProcAddress(hModule, lpProcName); if (farProc == null) throw (new Exception("")); try { pcon = Marshal.AllocHGlobal(Marshal.SizeOf(func)); Marshal.StructureToPtr(func, pcon, true); dreamduStruct(pcon); Marshal.PtrToStructure(pcon, func); } finally { Marshal.FreeHGlobal(pcon); } } //卸载 Dll public static void UnLoadDll() { bool ret = FreeLibrary(hModule); hModule = IntPtr.Zero; dreamduStruct = null; } public static bool GetIP(string name) { return func.Dreamdu_PGetIP(name); } public static void GetName(string name) { return func.Monkey_PGetName(name); } private static IntPtr hModule = IntPtr.Zero; private static GetDreamduFuns dreamduStruct = null; private static FUNDreamduStruct func = new Dreamdu_Struct(); private static IntPtr pcon = IntPtr.Zero;} 上面的C#接口就已经封装好了,仔细观察GetDreamduAddress函数kernel32.dll中此函数是返回FARPROC指针的,但是在这里我重新定义了一个委托来获取函数指针。 上面的C#接口就已经封装好了,可以使用下面方式调用。 class DreamduDLL{ Dreamdu.LoadDll("Dreamdu.dll"); Dreamdu.LoadFun("Dreamdu_GetDreamduStruct"); //获取ip bool hasIP = Dreamdu.GetIP("www."); if(hasIP) { //获取名称 Dreamdu.GetName("www./blog/"); } //使用完了别忘了卸载dll Dreamdu.UnLoadDll();} |
|
来自: ThinkTank_引擎 > 《SDK》