分享

C#动态调用非托管DLL

 miky 2008-04-07
C#动态调用非托管DLL 尝试着在C#下调用以前Delphi写的一些DLL,基本实现动态调用,传入回调函数,及调用带结构数组指针作为参数的函数. 虽然DllImport可以方便的静态调用DLL的函数,但在.net2.0中新增加了一个Marshal.GetDelegateForFunctionPointer 方法,可以将非托管函数指针转换为委托。 有了这个方法就可以用三个Windows API函数即:Loadlibrary,GetProcAddress和Freelibrary来实现动态调用DLL了.下面是实现DLL动态调用的静态类 using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Data; namespace Test { /// /// DLL加载类 /// internal class DynamicLoadDll { [DllImport("Kernel32")] public static extern int GetProcAddress(int handle, String funcname); [DllImport("Kernel32")] public static extern int LoadLibrary(String funcname); [DllImport("Kernel32")] public static extern int FreeLibrary(int handle); public static Delegate GetAddress(int dllModule, string functionname, Type t) { int addr = GetProcAddress(dllModule, functionname); if (addr == 0) return null; else return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t); } } Public class referDll { private int m_hDLL = 0; //DLL句柄 private delegate int ShowForm(IntPtr aHandle); private ShowForm m_ShowForm; private const string DLLNAEM = "XXX.dll"; m_hDLL = DllLoader.LoadLibrary(DLLNAEM); if (m_hDLL == 0) { MessageBox.Show("加载失败!") return; } m_ShowForm = (ShowForm) DllLoader.GetAddress(m_hPacsview, "ShowForm", typeof (ShowForm)); //使用ShowForm if (m_ShowForm != null) m_ShowForm(iHandle); //卸载DLL DllLoader.FreeLibrary(m_hDLL); } } 接着说说如何调用DLL中带结构数组指针作为参数的函数.在原来Delphi中定义如下: //一个结构定义如下 TStudyRec = Record UID : Array[0..127] of Char; end; TCharArray=Array[0..49] of TStudyRec; //在DLL中有如下函数 其中AStudys为TCharArray的指针 function Open(AStudys: Pointer): HRESULT; StdCall; 要在C#里正常调用,首先要定义出一个相同的结构 private struct StudyRec { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string UID; //名称 } 接着声明一个委托 private delegate int Open(IntPtr aStudys); 从DLL得到委托实例 private Open m_Open = (Open) DllLoader.GetAddress(m_hDLL, "Open", typeof (Open)); //m_hDLL为DLL指针 到此为止终于在C#里定义出相同的结果及函数了,下面就是要调用了,因为结构数组是要给非托管的DLL使用的,因此最关键的一点是要用Marshal.AllocHGlobal来分配好非托管内存,把结构数组放到内存中去,再把内存指针当作参数调用就OK啦 StudyRec[] arrStudyRec = new StudyRec[50]; int isize = Marshal.SizeOf(typeof (StudyRec)); IntPtr parrStudyRec = Marshal.AllocHGlobal(Marshal.SizeOf(isize*50)); int run = (int) parrStudyRec; for (int i = 0; i < 50; i++) { arrStudyRec[i].UID = i.tostring();//这里只是模拟,所以直接把i当作UID了 Marshal.StructureToPtr(arrStudyRec[i], (IntPtr) run, false); run += isize; } m_Open(parrStudyRec);

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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多