原文: c++中的导出方法:
这两天忙着把框架改为支持加载C++和Delphi的插件,来不及更新blog了。
原来的写的框架只支持c#插件,这个好做,直接用c#的反射功能便可。但是公司不是所有人都搞C#,也不是所有的程序C#都能很好的完成,又或者其他公司提供的API不是C#的,这个时候,就需要这个框架能够支持多种语言了。 废话不多说,进入正题。 上网一搜,C#加载非托管的dll,无非就是使用 DllImportAttribute 。然而,这个属性里面要指明dll所在的路径,因为又是写在属性中,因此是在编译的时候就已经把路径写死了,不能动态指定路径加载。 于是又找了下,终于发现了c#中的一个函数:Marshal.GetDelegateForFunctionPointer。这个函数的功能就是将非托管的函数指针转换为委托。至此,任务完成。Dll的功能无非提提供各种函数,组成所谓的API,有了上述的方法之后,在C#中定义相关的委托(方法的参数列表和参数类型要跟非托管的Dll的参数类型和参数列表对应,具体的对应请google),然后调用上述方法,将非托管的dll转换为相应的委托,这样就能调用非托管的dll了。 在C#中,我们定义相关的接口,在方法实现中调用相应的委托,这样,一个插件对象就完成了。下面给出相应的类库和使用实例。
1 public class LoadDll 2 { 3 #region Win32 API : Load dll 4 [DllImport( " kernel32.dll " )] 5 public static extern IntPtr LoadLibrary( string path); 6 7 [DllImport( " kernel32.dll " )] 8 public static extern IntPtr GetProcAddress(IntPtr lib, string funcName); 9 10 [DllImport( " kernel32.dll " )] 11 public static extern bool FreeLibrary(IntPtr lib); 12 13 [DllImport( " kernel32.dll " )] 14 public static extern IntPtr GetStdHandle( int nStdHandle); 15 16 [DllImport( " user32 " , EntryPoint = " CallWindowProc " )] 17 public static extern int CallWindowProc(IntPtr lpPreWndFunc, int hwnd, int msg, int wParam, int lParam); 18 #endregion 19 20 private IntPtr _dllLib; 21 22 /// <summary> 23 /// Initializes a new instance of the <see cref="LoadDll"/> class. 24 /// </summary> 25 public LoadDll() 26 { 27 28 } 29 30 /// <summary> 31 /// Initializes a new instance of the <see cref="LoadDll"/> class. 32 /// </summary> 33 /// <param name="path"> The path. </param> 34 public LoadDll( string path) 35 { 36 _dllLib = LoadLibrary(path); 37 } 38 39 /// <summary> 40 /// 注销对象时释放资源 41 /// <see cref="LoadDll"/> is reclaimed by garbage collection. 42 /// </summary> 43 ~ LoadDll() 44 { 45 FreeLibrary(_dllLib); 46 } 47 48 /// <summary> 49 /// 初始化dll的路径 50 /// </summary> 51 /// <param name="path"> The path. </param> 52 public void InitPath( string path) 53 { 54 if (_dllLib == IntPtr.Zero) 55 _dllLib = LoadLibrary(path); 56 } 57 58 /// <summary> 59 /// 根据非托管的dll中的方法名称映射成托管的委托类型 60 /// </summary> 61 /// <param name="methodName"> 非托管的dll中的方法名称 </param> 62 /// <param name="methodType"> 托管的委托类型 </param> 63 /// <returns></returns> 64 public Delegate InvokeMethod( string methodName, Type methodType) 65 { 66 // 获取非托管的dll中方法的地址 67 var methodPtr = GetProcAddress(_dllLib, methodName); 68 // 将非托管的方法转换为委托 69 return Marshal.GetDelegateForFunctionPointer(methodPtr, methodType); 70 } 71 }
调用:
1 loadDll = new LoadDll(path); 2 stop = (StopHandler)loadDll.InvokeMethod( " stop " , typeof (StopHandler)); 3 start = (StartHandler)loadDll.InvokeMethod( " start " , typeof (StartHandler)); 4 init = (InitHandler)loadDll.InvokeMethod( " init " , typeof (InitHandler)); 5 query = (QueryHandler)loadDll.InvokeMethod( " query " , typeof (QueryHandler)); 6 setDatabaseInfo = (SetDatabaseInfoHandler)loadDll.InvokeMethod( " setDatabaseInfo " , typeof (SetDatabaseInfoHandler)); 7 setMonitorInfo = (SetMonitorInfoHandler)loadDll.InvokeMethod( " setMonitorInfo " , typeof (SetMonitorInfoHandler));
1 /// 插件导出方法 2 extern " C " __declspec(dllexport) void setDatabaseInfo(LPCTSTR dbServer, LPCTSTR dbUser, LPCTSTR dbPass, LPCTSTR dbName); 3 extern " C " __declspec(dllexport) void setMonitorInfo(LPCTSTR _agentBm, LPCTSTR _com); 4 extern " C " __declspec(dllexport) void init(); 5 extern " C " __declspec(dllexport) void start(); 6 extern " C " __declspec(dllexport) void stop(); 7 extern " C " __declspec(dllexport) LPCTSTR query(LPCTSTR devname, LPCTSTR id);
C#中的委托
1 /// <summary> 2 /// 处理Stop事件 3 /// </summary> 4 public delegate void StopHandler(); 5 /// <summary> 6 /// 处理Start事件 7 /// </summary> 8 public delegate void StartHandler(); 9 /// <summary> 10 /// 处理Init事件 11 /// </summary> 12 public delegate void InitHandler(); 13 /// <summary> 14 /// 处理Query事件 15 /// </summary> 16 public delegate string QueryHandler( string devName, string id); 17 /// <summary> 18 /// 处理SetDataBaseInfo事件 19 /// </summary> 20 public delegate void SetDatabaseInfoHandler( string server, string user, string password, string dbName); 21 /// <summary> 22 /// 处理SetMonitorInfo事件 23 /// </summary> 24 public delegate void SetMonitorInfoHandler( string agentBm, string com);
接下来怎么搞,你们都懂的
posted on 2018-07-28 23:37 阅读( ...) 评论( ...)