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

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

目录
相关文章
|
11月前
|
XML 测试技术 API
利用C#开发ONVIF客户端和集成RTSP播放功能
利用C#开发ONVIF客户端和集成RTSP播放功能
4993 123
|
物联网 数据处理 C#
C#实现上位机开发,串口通信,读写串口数据并处理16进制数据
C#实现上位机开发,串口通信,读写串口数据并处理16进制数据。在自动化、物联网以及工业控制行业中,上位机开发是一项重要的技能。本教程主要介绍使用C#进行上位机开发,重点在于串口通信和数据处理。
3042 82
|
IDE 开发工具 C语言
C++一分钟之-嵌入式编程与裸机开发
通过这些内容的详细介绍和实例解析,希望能帮助您深入理解C++在嵌入式编程与裸机开发中的应用,提高开发效率和代码质量。
588 13
|
SQL 小程序 API
如何运用C#.NET技术快速开发一套掌上医院系统?
本方案基于C#.NET技术快速构建掌上医院系统,结合模块化开发理念与医院信息化需求。核心功能涵盖用户端的预约挂号、在线问诊、报告查询等,以及管理端的排班管理和数据统计。采用.NET Core Web API与uni-app实现前后端分离,支持跨平台小程序开发。数据库选用SQL Server 2012,并通过读写分离与索引优化提升性能。部署方案包括Windows Server与负载均衡设计,确保高可用性。同时针对API差异、数据库老化及高并发等问题制定应对措施,保障系统稳定运行。推荐使用Postman、Redgate等工具辅助开发,提升效率与质量。
685 0
|
缓存 算法 安全
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
809 12
基于 C# 编写的 Visual Studio 文件编码显示与修改扩展插件
基于 C# 编写的 Visual Studio 文件编码显示与修改扩展插件
603 9
|
缓存 C# 开发者
C# 一分钟浅谈:Blazor Server 端开发
本文介绍了 Blazor Server,一种基于 .NET 的 Web 开发模型,允许使用 C# 和 Razor 语法构建交互式 Web 应用。文章从基础概念、创建应用、常见问题及解决方案、易错点及避免方法等方面详细讲解,帮助开发者快速上手并提高开发效率。
596 2
|
开发框架 缓存 .NET
C# 一分钟浅谈:Blazor Server 端开发
Blazor Server 是基于 ASP.NET Core 的框架,允许使用 C# 和 Razor 语法构建交互式 Web 应用。本文介绍 Blazor Server 的基本概念、快速入门、常见问题及解决方案,帮助开发者快速上手。涵盖创建应用、基本组件、数据绑定、状态管理、跨组件通信、错误处理和性能优化等内容。
1138 1
|
11月前
|
XML 前端开发 C#
C#编程实践:解析HTML文档并执行元素匹配
通过上述步骤,可以在C#中有效地解析HTML文档并执行元素匹配。HtmlAgilityPack提供了一个强大而灵活的工具集,可以处理各种HTML解析任务。
437 19
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
486 3