最近看到有同学在问C#如何动态加载C的DLL,所以在这里跟大家分享一下!
本文以VS2013来做开发示例,请知悉!(注C#项目仅设置了Debug解决方案,release一样的更改即可)。
如下图,工程分为3个:
TestDLL是导出库,导出 test_hello 函数作为要被加载的测试DLL;
DynamicLoadDemo 为动态加载C#动态加载DLL的方式;(注:LoadLibrary、GetProcAddress、FreeLibrary)
StaticLoadDemo为为静态加载C#动态加载DLL的方式。(注:DllImport)
TestDLL:源码展示
TestDLL.h #pragma once #ifdef TESTDLL_EXPORTS #define TESTDLL_API _declspec(dllexport) #else #define TESTDLL_API _declspec(dllimport) #endif #ifdef __cplusplus extern "C"{ #endif TESTDLL_API int test_hello(); #ifdef __cplusplus }; #endif
TestDLL.cpp #include "TestDLL.h" #ifdef __cplusplus extern "C"{ #endif TESTDLL_API int test_hello() { ::MessageBoxA(NULL,"test_hello","msg",0); return 1; } #ifdef __cplusplus }; #endif
通过以上代码就顺利的导出了函数test_hello。 depends查看如下图
好了下面我们进入正题:
DynamicLoadDemo :
在C++ 中 使用LoadLibrary、GetProcAddress、FreeLibrary三个函数即可实现DLL的动态加载(不清楚的同学请自动MSDN)。
C#动态load也是用的这3个函数实现,但是C#不提供这些函数的引用方式,那么我们自己就加载系统DLL来获得这三个函数的调用方法!
其实使用的方法也就是DllImport。
如下图
下面是测试代码,测试工程很简单只有一个Button,代码如下
// int test_hello(); public delegate int test_hello_fn(); private void load_click(object sender, EventArgs e) { Int32 hModule = 0; int iResult = 0; do { hModule = CDynamicLoadHelper.LoadLibrary("TestDLL.dll"); if(0 == hModule) { iResult = -1; break; } // IntPtr temp_fn = IntPtr.Zero; temp_fn = CDynamicLoadHelper.GetProcAddress(hModule,"test_hello");//get c export fun test_hello if(IntPtr.Zero == temp_fn) { iResult = -2; break; } test_hello_fn fn = (test_hello_fn)Marshal.GetDelegateForFunctionPointer(temp_fn, typeof(test_hello_fn)); iResult = fn(); } while (false); if(0 != hModule) { CDynamicLoadHelper.FreeLibrary(hModule); hModule = 0; } MessageBox.Show("test over result is:" + iResult); }
StaticLoadDemo:
直接使用C#的DllImport 引入函数,此时Demo提供2中测试方法,一种带异常捕捉,另外一种不带异常捕捉。
load_catch_click(有异常捕捉的)
load_click(无异常捕捉)
[DllImport("TestDLL.dll", EntryPoint = "test_hello")] public static extern Int32 test_hello_fn(); private void load_catch_click(object sender, EventArgs e) { int iResult = 0; try { iResult = test_hello_fn(); }catch { iResult = -1; } MessageBox.Show("test over result is:" + iResult); } private void load_click(object sender, EventArgs e) { int iResult = test_hello_fn(); MessageBox.Show("test over result is:" + iResult); }
运行效果如下:
DynamicLoadDemo.exe:
可以看到第一次弹出的test_hello为DLL弹出的对话框,第二个对话框为C#的结果提示框。
StaticLoadDemo.exe
(略)正常情况下运行情况和DynamicLoadDemo.exe一样(如上图),
正常情况下DLL都被正常加载到了。我们这里做一个特俗的事情,就是把当前目录的TestDLL.dll 删掉。看运行情况会怎么样?
DynamicLoadDemo.exe反映正常没有异常捕捉也发现DLL 不存在,运行结果在意料之中。(没有跑飞)
StaticLoadDemo.exe
有异常捕捉的
没有异常捕捉的
可以看到没有异常捕捉的直接报错了,
文章完!那种加载方式还得看大家的选择,本人对C#仅停留于DEMO层次不评价那种方式更优!
源码包CSDN:http://download.csdn.net/detail/u012251006/9912376