(二)动态装载、调用DLL中的非托管函数
在上面已经说明了如何用DllImport调用DLL中的非托管函数,但是这个是全局的函数,假若DLL中的非托管函数有一个静态变量S,每次调用这个函数的时候 , 静态变量S就自动加1 。结果,当需要重新计数时,就不能得出想要的结果 。
下面将用例子说明:
1.DLL的创建
1)启动Visual C++ 6.0;
2)新建一个“Win32 Dynamic-Link Library”工程,工程名称为“Count”;
3)在“Dll kind”选择界面中选择“A simple dll project”;
4)打开Count.cpp,添加如下代码:
// 导出函数,使用“ _stdcall ” 标准调用
extern "C" _declspec(dllexport)int _stdcall count(int init);
int _stdcall count(int init)
{//count 函数,使用参数 init 初始化静态的整形变量 S,并使 S 自加 1 后返回该值
static int S=init;
【c语言将函数封装到静态库 c语言封装函数是什么意思】S++;
return S;
}
5)按“F7”进行编译,得到Count.dll(在工程目录下的Debug文件夹中) 。
2.用DllImport调用DLL中的count函数
1)打开项目“Tzb” , 向“Form1”窗体中添加一个按钮 。
2)改变按钮的属性:Name为 “B2” , Text为 “用DllImport调用DLL中count函数”,并将按钮B1调整到适当大?。频绞实蔽恢?。
3)打开“Form1.cs”代码视图,使用关键字 static 和 extern 声明方法“count”,并使其具有来自 Count.dll 的导出函数count的实现 , 代码如下:
[DllImport("Count.dll")]
static extern int count(int init);
4)在“Form1.cs[设计]”视图中双击按钮B2,在“B2_Click”方法体内添加如下代码:
MessageBox.Show(" 用 DllImport 调用 DLL 中的 count 函数,n 传入的实参为 0 ,得到的结果是: "+count(0).ToString()," 挑战杯 ");
MessageBox.Show(" 用 DllImport 调用 DLL 中的 count 函数 , n 传入的实参为 10,得到的结果是: "+count(10).ToString()+"n 结果可不是想要的 11 哦?。。?"," 挑战杯 ");
MessageBox.Show(" 所得结果表明: n 用 DllImport 调用 DLL 中的非托管 n 函数是全局的、静态的函数?。。?"," 挑战杯 ");
5)把Count.dll复制到项目“Tzb”的binDebug文件夹中,按“F5”运行该程序,并点击按钮B2,便弹出如下三个提示框 。
第1个提示框显示的是调用“count(0)”的结果,第2个提示框显示的是调用“count(10)”的结果,由所得结果可以证明“用DllImport调用DLL中的非托管函数是全局的、静态的函数” 。所以,有时候并不能达到我们目的,因此我们需要使用下面所介绍的方法:C#动态调用
DLL中的函数 。
3.C#动态调用DLL中的函数
因为C#中使用DllImport是不能像动态load/unload assembly那样,所以只能借助API函数了 。在kernel32.dll中,与动态库调用有关的函数包括[3]:
1)LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库;
2)GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL内部地址;
3)FreeLibrary(或MFC的AfxFreeLibrary),释放动态链接库 。
它们的原型分别是:
HMODULE LoadLibrary(LPCTSTR lpFileName);
FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);
BOOL FreeLibrary(HMODULE hModule);
现在,我们可以用IntPtr hModule=LoadLibrary(“Count.dll”);来获得Dll的句柄,用IntPtr farProc=GetProcAddress(hModule,”_count@4”);来获得函数的入口地址 。
但是,知道函数的入口地址后,怎样调用这个函数呢?因为在C#中是没有函数指针的,没有像C++那样的函数指针调用方式来调用函数,所以我们得借助其它方法 。经过研究,发现我们可以通过结合使用System.Reflection.Emit及System.Reflection.Assembly里的类和函数达到我们的目的 。为了以后使用方便及实现代码的复用,我们可以编写一个类 。
推荐阅读
- 微信直播怎么设置观众隐私,看微信直播怎么隐藏自己的名字
- 财务转做erp系统运维,erp财务顾问转行
- 明德公益公众号关注,明德公益研究中心
- 葫芦侠恋爱养成类游戏下载,葫芦侠官方正版
- linux自动排版命令 linux排序命令
- saprfc接口,sap接口方式idoc
- 微信小程序资质主体,小程序资质主体不一致
- 直播的值可以组什么,直播的播可以组什么词语
- python字典中放函数 python字典作为函数参数