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

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

目录
打赏
0
0
0
0
216
分享
相关文章
C++一分钟之-嵌入式编程与裸机开发
通过这些内容的详细介绍和实例解析,希望能帮助您深入理解C++在嵌入式编程与裸机开发中的应用,提高开发效率和代码质量。
80 13
|
4月前
|
C#
基于 C# 编写的 Visual Studio 文件编码显示与修改扩展插件
基于 C# 编写的 Visual Studio 文件编码显示与修改扩展插件
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
5月前
|
C#一分钟浅谈:ReSharper 插件增强开发效率
【10月更文挑战第25天】ReSharper 是 JetBrains 开发的一款 Visual Studio 插件,旨在提高 .NET 开发者的生产力。它通过代码分析、重构、导航等功能,帮助开发者避免常见错误,提升代码质量和开发效率。本文将通过具体代码案例,详细介绍 ReSharper 的常见功能及其应用。
132 1
那C++适合开发哪些项目
C++ 是一种功能强大、应用广泛的编程语言,适合开发多种类型的项目。它在游戏开发、操作系统、嵌入式系统、科学计算、金融、图形图像处理、数据库管理、网络通信、人工智能、虚拟现实、航空航天等领域都有广泛应用。C++ 以其高性能、内存管理和跨平台兼容性等优势,成为众多开发者的选择。
WK
219 1
C++和Java哪个更适合开发移动应用
本文对比了C++和Java在移动应用开发中的优劣,从市场需求、学习难度、开发效率、跨平台性和应用领域等方面进行了详细分析。Java在Android开发中占据优势,而C++则适合对性能要求较高的场景。选择应根据具体需求和个人偏好综合考虑。
WK
132 0
WK
|
5月前
|
C++和Java哪个更适合开发web网站
在Web开发领域,C++和Java各具优势。C++以其高性能、低级控制和跨平台性著称,适用于需要高吞吐量和低延迟的场景,如实时交易系统和在线游戏服务器。Java则凭借其跨平台性、丰富的生态系统和强大的安全性,广泛应用于企业级Web开发,如企业管理系统和电子商务平台。选择时需根据项目需求和技术储备综合考虑。
WK
233 0
如何使用 C++ 开发 Redis 模块
如何使用 C++ 开发 Redis 模块
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
45 16
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等