这两天忙着把框架改为支持加载 C++ 和 Delphi 的插件, 来不及更新 blog 了.
原来的写的框架只支持 c# 插件, 这个好做, 直接用 c# 的反射功能便可. 但是公司不是所有人都搞 C#, 也不是所有的程序 C# 都能很好的完成, 又或者其他公司提供的 API 不是 C# 的, 这个时候, 就需要这个框架能够支持多种语言了.
废话不多说, 进入正题.
上网一搜, C# 加载非托管的 dll, 无非就是使用 DllImportAttribute . 然而, 这个属性里面要指明 dll 所在的路径, 因为又是写在属性中, 因此是在编译的时候就已经把路径写死了, 不能动态指定路径加载.
于是又找了下, 终于发现了 c# 中的一个函数: Marshal.GetDelegateForFunctionPointer. 这个函数的功能就是将非托管的函数指针转换为委托. 至此, 任务完成. Dll 的功能无非提提供各种函数, 组成所谓的 API, 有了上述的方法之后, 在 C# 中定义相关的委托 (方法的参数列表和参数类型要跟非托管的 Dll 的参数类型和参数列表对应, 具体的对应请 google), 然后调用上述方法, 将非托管的 dll 转换为相应的委托, 这样就能调用非托管的 dll 了.
在 C# 中, 我们定义相关的接口, 在方法实现中调用相应的委托, 这样, 一个插件对象就完成了. 下面给出相应的类库和使用实例.
- public class LoadDll
- {
- #region Win32 API : Load dll
- [DllImport("kernel32.dll")]
- public static extern IntPtr LoadLibrary(string path);
- [DllImport("kernel32.dll")]
- public static extern IntPtr GetProcAddress(IntPtr lib, string funcName);
- [DllImport("kernel32.dll")]
- public static extern bool FreeLibrary(IntPtr lib);
- [DllImport("kernel32.dll")]
- public static extern IntPtr GetStdHandle(int nStdHandle);
- [DllImport("user32", EntryPoint = "CallWindowProc")]
- public static extern int CallWindowProc(IntPtr lpPreWndFunc, int hwnd, int msg, int wParam, int lParam);
- #endregion
- private IntPtr _dllLib;
- /// <summary>
- /// Initializes a new instance of the <see cref="LoadDll"/> class.
- /// </summary>
- public LoadDll()
- {
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="LoadDll"/> class.
- /// </summary>
- /// <param name="path">The path.</param>
- public LoadDll(string path)
- {
- _dllLib = LoadLibrary(path);
- }
- /// <summary>
- /// 注销对象时释放资源
- /// <see cref="LoadDll"/> is reclaimed by garbage collection.
- /// </summary>
- ~LoadDll()
- {
- FreeLibrary(_dllLib);
- }
- /// <summary>
- /// 初始化 dll 的路径
- /// </summary>
- /// <param name="path">The path.</param>
- public void InitPath(string path)
- {
- if (_dllLib == IntPtr.Zero)
- _dllLib = LoadLibrary(path);
- }
- /// <summary>
- /// 根据非托管的 dll 中的方法名称映射成托管的委托类型
- /// </summary>
- /// <param name="methodName"> 非托管的 dll 中的方法名称 </param>
- /// <param name="methodType"> 托管的委托类型 </param>
- /// <returns></returns>
- public Delegate InvokeMethod(string methodName, Type methodType)
- {
- // 获取非托管的 dll 中方法的地址
- var methodPtr = GetProcAddress(_dllLib, methodName);
- // 将非托管的方法转换为委托
- return Marshal.GetDelegateForFunctionPointer(methodPtr, methodType);
- }
- }
调用:
- loadDll = new LoadDll(path);
- stop = (StopHandler)loadDll.InvokeMethod("stop", typeof(StopHandler));
- start = (StartHandler)loadDll.InvokeMethod("start", typeof(StartHandler));
- init = (InitHandler)loadDll.InvokeMethod("init", typeof(InitHandler));
- query = (QueryHandler)loadDll.InvokeMethod("query", typeof(QueryHandler));
- setDatabaseInfo = (SetDatabaseInfoHandler)loadDll.InvokeMethod("setDatabaseInfo", typeof(SetDatabaseInfoHandler));
- setMonitorInfo = (SetMonitorInfoHandler)loadDll.InvokeMethod("setMonitorInfo", typeof(SetMonitorInfoHandler));
c++ 中的导出方法:
- /// 插件导出方法
- extern "C" __declspec(dllexport) void setDatabaseInfo(LPCTSTR dbServer, LPCTSTR dbUser, LPCTSTR dbPass, LPCTSTR dbName);
- extern "C" __declspec(dllexport) void setMonitorInfo(LPCTSTR _agentBm, LPCTSTR _com);
- extern "C" __declspec(dllexport) void init();
- extern "C" __declspec(dllexport) void start();
- extern "C" __declspec(dllexport) void stop();
- extern "C" __declspec(dllexport) LPCTSTR query(LPCTSTR devname, LPCTSTR id);
- C# 中的委托
- ///<summary>
- /// 处理 Stop 事件
- ///</summary>
- publicdelegatevoid StopHandler();
- ///<summary>
- /// 处理 Start 事件
- ///</summary>
- publicdelegatevoid StartHandler();
- ///<summary>
- /// 处理 Init 事件
- ///</summary>
- publicdelegatevoid InitHandler();
- ///<summary>
- /// 处理 Query 事件
- ///</summary>
- publicdelegatestring QueryHandler(string devName, string id);
- ///<summary>
- /// 处理 SetDataBaseInfo 事件
- ///</summary>
- publicdelegatevoid SetDatabaseInfoHandler(string server,string user,string password,string dbName);
- ///<summary>
- /// 处理 SetMonitorInfo 事件
- ///</summary>
- publicdelegatevoid SetMonitorInfoHandler(string agentBm, string com);
接下来怎么搞, 你们都懂的
来源: http://www.bubuko.com/infodetail-2704491.html