C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件

简介: 原文:C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件       这两天忙着把框架改为支持加载C++和Delphi的插件,来不及更新blog了。      原来的写的框架只支持c#插件,这个好做,直接用c#的反射功能便可。
原文: C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件

      这两天忙着把框架改为支持加载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));


c++中的导出方法:

 

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);

接下来怎么搞,你们都懂的

目录
相关文章
|
2天前
|
测试技术 Go C#
C#一分钟浅谈:ReSharper 插件增强开发效率
【10月更文挑战第25天】ReSharper 是 JetBrains 开发的一款 Visual Studio 插件,旨在提高 .NET 开发者的生产力。它通过代码分析、重构、导航等功能,帮助开发者避免常见错误,提升代码质量和开发效率。本文将通过具体代码案例,详细介绍 ReSharper 的常见功能及其应用。
11 1
|
8天前
|
C# Python
使用wxpython开发跨平台桌面应用,对wxpython控件实现类似C#扩展函数处理的探究
【10月更文挑战第30天】使用 `wxPython` 开发跨平台桌面应用时,可以通过创建辅助类来模拟 C# 扩展函数的功能。具体步骤包括:1. 创建辅助类 `WxWidgetHelpers`;2. 在该类中定义静态方法,如 `set_button_color`;3. 在应用中调用这些方法。这种方法提高了代码的可读性和可维护性,无需修改 `wxPython` 库即可为控件添加自定义功能。但需要注意显式调用方法和避免命名冲突。
|
15天前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
26 1
|
22天前
|
开发框架 NoSQL MongoDB
C#/.NET/.NET Core开发实战教程集合
C#/.NET/.NET Core开发实战教程集合
|
26天前
|
Linux C++
Linux c/c++文件的基本操作
在Linux环境下使用C/C++进行文件的基本操作,包括文件的创建、写入、读取、关闭以及文件描述符的定位。
18 0
Linux c/c++文件的基本操作
|
26天前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
37 0
|
26天前
|
Linux C++
Linux c/c++文件移动
这篇文章介绍了在Linux环境下,使用C/C++语言通过命令方式和文件操作方式实现文件移动的方法。
55 0
|
27天前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
43 0
|
2月前
|
Linux API C++
超级好用的C++实用库之文件目录操作
超级好用的C++实用库之文件目录操作
28 0
|
18天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
21 4