C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件
原文: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         publicdelegatevoid StopHandler();
5         ///<summary>
6         /// 处理Start事件
7         ///</summary>
8         publicdelegatevoid StartHandler();
9         ///<summary>
10         /// 处理Init事件
11         ///</summary>
12         publicdelegatevoid InitHandler();
13         ///<summary>
14         /// 处理Query事件
15         ///</summary>
16         publicdelegatestring QueryHandler(string devName, string id);
17         ///<summary>
18         /// 处理SetDataBaseInfo事件
19         ///</summary>
20         publicdelegatevoid SetDatabaseInfoHandler(string server,string user,string password,string dbName);
21         ///<summary>
22         /// 处理SetMonitorInfo事件
23         ///</summary>
24         publicdelegatevoid SetMonitorInfoHandler(string agentBm, string com);

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

posted on 2019-03-15 10:59 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/10535671.html

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

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

    这两天忙着把框架改为支持加载C++和Delphi的插件,来不及更新blog了.       原来的写的框架只支持c#插件,这个好做,直接用c#的反射功能便可.但是公司不是所有人都搞C#,也不是所有的程 ...

  2. mkl_def.dll文件加载失败

    mkl_def.dll文件加载失败 下载 mkl_def.dll文件的下载地址如下:Fix mkl_def.dll related errors in Windows 7, 8 or 10 | DLL ...

  3. 逆战d3dx10_43.dll文件加载失败及dll文件缺失损坏修复解决方案

    废话前言:本人对电脑底层了解不太深,因此在前些天因为idea出现一个显示"构建进程终止异常"的bug,尝试网上很多解决方案都没有成功,无奈之下只好重装系统.但重装系统后,逆战又显示 ...

  4. 成功解决将crx后缀文件加载到谷歌浏览器作为插件使用

    成功解决将crx后缀文件加载到谷歌浏览器作为插件使用 目录 解决问题 解决思路 解决方法 1.下载crx文件

  5. 用 C 语言开发一门编程语言 — 字符串与文件加载

    目录 文章目录 目录 前文列表 字符串 读取字符串 注释 文件加载函数 命令行参数 打印函数 报错函数 源代码 前文列表 <用 C 语言开发一门编程语言 - 交互式解析器> <用 C ...

  6. cad二次开发——自动运行dll,加载菜单(收集)

    1.自动加载dll的方法(个人觉得下面第4个方法会更方便) cad加载dll_实现CAD插件启动自动加载的三种方法_weixin_39774556的博客-CSDN博客从网上或者别处淘来的CAD插件,效 ...

  7. sql文件加载出错_四十二、SparkSQL通用数据源加载(load)和保存(save)

    SparkSQL能用数据加载(load)和保存(save) 对于Spark SQL的DataFrame来说,无论是从什么数据源创建出来的DataFrame,都有一些共同的load和save操作.loa ...

  8. 工控机的io开发_C#调用工控机dll文件,实现对IO的控制

    本文旨在记录,C#通过调用外部DLL文件实现对Nuvo3120工控机IO口的控制. 前期,了解了C++中.c\.h\.lib文件的区别,以及用这些文件生成DLL的方法,后面通过厂家直接找到了WDT_D ...

  9. Cocos2d之Texture2D类详解之将文件加载成Texture2D对象

    一.声明 笔者以cocos2d框架cocos2d-x-3.3rc0版本的源码做分析.本文为笔者原创,允许转载和分享,只要注明文章出处即可. 二.简介 Texture2D类简介 Texture2D类允许 ...

  10. WSAStartup()函数以及DLL的加载

    本节讲解 Windows 下 DLL 的加载,学习 Linux Socket 的读者可以跳过. WinSock(Windows Socket)编程依赖于系统提供的动态链接库(DLL),有两个版本: 较 ...

最新文章

  1. sqlmap 获取mysql密码_利用sqlmap 获取管理员账号密码
  2. 一文读懂神经网络初始化!吴恩达Deeplearning.ai最新干货
  3. Visual Studio2005的加载此属性页时出错的解决办法(转)
  4. 英国加密期货交易所增加比特币现金合约
  5. POJ 3253 -- Fence Repair
  6. leetcode 1345. Jump Game IV | 1345. 跳跃游戏 IV(BFS)
  7. php课程设计实验心得,PHP程序设计教程实验及课程设计
  8. python中的doctest_Python测试框架doctest
  9. 如何移动没有标题的窗体
  10. Git64位windows版Git-2.10.1-64-bit.exe
  11. Axure8.0AxureRP8实战手册
  12. 信道编码与matlab仿真 刘东华,【网安学术】交织技术对信道编码的性能影响研究...
  13. 【网络】路由器和交换机区别,什么是网关
  14. [NIPS 2018] Stacked Semantics-Guided Attention Model for Fine-Grained Zero-Shot Learning
  15. 2021秋软工实践第二次结对编程作业
  16. 多云时代下数据管理技术_建立一个混合的多云数据湖并使用Apache Spark执行数据处理...
  17. 硬件工程师(电源设计)
  18. springboot 应用:异常管理,应用启动过程,应用监控 Prometheus 和 Grafana
  19. [译]5步分析pdf文件
  20. Win10杀死进程方式

热门文章

  1. 数据库系统概论 -- 第一章 绪论(知识点)
  2. jdi屏幕斜纹_如何看待小米6使用有斜纹的jdi屏幕?
  3. 国家计算机房机柜接地图集,中国铁塔机房及室外机柜标准图集.pdf
  4. ctf 改变图片高度_在Unity中 改变地形(Terrain),并加上水面、树、草地、材质(地板上色)...
  5. 实现了某一个接口的匿名类的例子_“全栈2019”Java多线程第三章:创建多线程之实现Runnable接口...
  6. C语言向文件写入学生信息并读取显示出来
  7. linux2.6.34编译安装,busybox linux-2.6.2 编译安装中碰到的若干问题
  8. 教育部计算机考研大纲,2021考研计算机大纲计算机组成原理部分考查内容
  9. Google Cloud 虚拟机 Virtual Machines
  10. 自动驾驶1-2 欢迎来到课程 Welcome to the Course