【转】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);
接下來怎么搞,你們都懂的
?
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注馬非碼的微信公眾號,我會將我的文章推送給您,并和您一起分享我日常閱讀過的優質文章。本文版權歸作者和博客園共有,來源網址:http://www.cnblogs.com/marvin/歡迎各位轉載,但是未經作者本人同意,轉載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責總結
以上是生活随笔為你收集整理的【转】C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 油价飙升!韩国卡车司机罢工:一月工资只够
- 下一篇: LSGO软件技术团队2015~2016学