分享

C#调用C++动态链接库中的函数指针与函数指针结构

 ThinkTank_引擎 2015-01-30

这几天做项目时,遇到了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();}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多