博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件
阅读量:5086 次
发布时间:2019-06-13

本文共 4308 字,大约阅读时间需要 14 分钟。

原文:

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

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

posted on
2018-07-28 23:37 阅读(
...) 评论(
...)

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

你可能感兴趣的文章
PAT 1001-1010 题解
查看>>
创龙TMS320C6748开发板串口和中断学习笔记
查看>>
01 C语言程序设计--01 C语言基础--第3章 基本数据类型01
查看>>
Java 反射机制详解(上)
查看>>
oracle drop table(表)数据恢复方法
查看>>
编译LAMP部署动态网站环境
查看>>
Java 8 新的时间日期 API
查看>>
PHP基本语法
查看>>
Linux命令应用大词典-第8章 日期和时间
查看>>
jenkins+maven+svn构建项目,及远程部署war包到tomcat上
查看>>
图解CSS3之弹性盒模型篇(display:box / display:inline-box)
查看>>
【iOS】UIImageView 点击事件
查看>>
HDOJ 1233 还是畅通工程
查看>>
垃圾回收机制
查看>>
C# lambda表达式及初始化器
查看>>
Spring Boot 静态资源处理
查看>>
nginx vhost配置
查看>>
Vue 爬坑之路(二)—— 组件之间的数据传递
查看>>
Mysql客户端下载地址
查看>>
Apache 2.2, PHP 5, and MySQL 5
查看>>