在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一,打开Windows系统文件夹,你会发现文件夹中有很多DLL文件,Windows就是将一些主要的系统功能以DLL模块的形式实现。 1)使用较少的资源 (一) 、调用DLL中的非托管函数一般方法 DLL文件必须位于程序当前目录或系统定义的查询路径中(即:系统环境变量中Path所设置的路径)。 C#例子: 1. 启动VS.NET,新建一个项目,项目名称为“Tzb”,模板为“Windows 应用程序”。 [DllImport("user32.dll", EntryPoint="MessageBoxA")] static extern int MsgBox(int hWnd, string msg, string caption, int type); 然后在“B1_Click”方法体内添加如下代码,以调用方法“MsgBox”: 7.代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll", EntryPoint = "MessageBoxA")] static extern int MsgBox2(int hWnd, string msg, string caption, int type); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { MsgBox2(0, " 这就是用 DllImport 调用 DLL 弹出的提示框哦! ", " 挑战杯 ", 0x30); } private void button2_Click(object sender, EventArgs e) { MsgBox2(0, " 这就是用 DllImport 调用 DLL 弹出的提示框哦222222f! ", " 222222 ", 0x30); } } } (二) 动态装载、调用DLL中的非托管函数 // 导出函数,使用“ _stdcall ” 标准调用 extern "C" _declspec(dllexport)int _stdcall count(int init); int _stdcall count(int init) {//count 函数,使用参数 init 初始化静态的整形变量 S ,并使 S 自加 1 后返回该值 static int S=init; S++; return S; } 5) 、按“F7”进行编译,得到Count.dll(在工程目录下的Debug文件夹中)。 [DllImport("Count.dll")] static extern int count(int init); 4) 、 在“Form1.cs[设计]”视图中双击按钮B2,在“B2_Click”方法体内添加如下代码: 第1个提示框显示的是调用“count(0)”的结果,第2个提示框显示的是调用“count(10)”的结果,由所得结果可以证明“用DllImport调用DLL中的非托管函数是全局的、静态的函数”。所以,有时候并不能达到我们目的,因此我们需要使用下面所介绍的方法:C#动态调用DLL中的函数。 ①LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。 using System.Runtime.InteropServices; // 用 DllImport 需用此 命名空间 using System.Reflection; // 使用 Assembly 类需用此 命名空间 using System.Reflection.Emit; // 使用 ILGenerator 需用此 命名空间 在“public class dld”上面添加如下代码声明参数传递方式枚举: /// <summary> /// 参数传递方式枚举 ,ByValue 表示值传递 ,ByRef 表示址传递 /// </summary> public enum ModePass { ByValue = 0x0001, ByRef = 0x0002 } 3.声明LoadLibrary、GetProcAddress、FreeLibrary及私有变量hModule和farProc: /// <summary> /// 原型是 :HMODULE LoadLibrary(LPCTSTR lpFileName); /// </summary> /// <param name="lpFileName">DLL 文件名 </param> /// <returns> 函数库模块的句柄 </returns> [DllImport("kernel32.dll")] static extern IntPtr LoadLibrary(string lpFileName); /// <summary> /// 原型是 : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName); /// </summary> /// <param name="hModule"> 包含需调用函数的函数库模块的句柄 </param> /// <param name="lpProcName"> 调用函数的名称 </param> /// <returns> 函数指针 </returns> [DllImport("kernel32.dll")] static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); /// <summary> /// 原型是 : BOOL FreeLibrary(HMODULE hModule); /// </summary> /// <param name="hModule"> 需释放的函数库模块的句柄 </param> /// <returns> 是否已释放指定的 Dll</returns> [DllImport("kernel32",EntryPoint="FreeLibrary",SetLastError=true)] static extern bool FreeLibrary(IntPtr hModule); /// <summary> /// Loadlibrary 返回的函数库模块的句柄 /// </summary> private IntPtr hModule=IntPtr.Zero; /// <summary> /// GetProcAddress 返回的函数指针 /// </summary> private IntPtr farProc=IntPtr.Zero; 4.添加LoadDll方法,并为了调用时方便,重载了这个方法: /// <summary> /// 装载 Dll /// </summary> /// <param name="lpFileName">DLL 文件名 </param> public void LoadDll(string lpFileName) { hModule=LoadLibrary(lpFileName); if(hModule==IntPtr.Zero) throw(new Exception(" 没有找到 :"+lpFileName+"." )); } 若已有已装载Dll的句柄,可以使用LoadDll方法的第二个版本: public void LoadDll(IntPtr HMODULE) { if(HMODULE==IntPtr.Zero) throw(new Exception(" 所传入的函数库模块的句柄 HMODULE 为空 ." )); hModule=HMODULE; } 5. 添加LoadFun方法,并为了调用时方便,也重载了这个方法,方法的具体代码及注释如下: /// <summary> /// 获得函数指针 /// </summary> /// <param name="lpProcName"> 调用函数的名称 </param> public void LoadFun(string lpProcName) { // 若函数库模块的句柄为空,则抛出异常 if(hModule==IntPtr.Zero) throw(new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !")); // 取得函数指针 farProc = GetProcAddress(hModule,lpProcName); // 若函数指针,则抛出异常 if(farProc==IntPtr.Zero) throw(new Exception(" 没有找到 :"+lpProcName+" 这个函数的入口点 ")); } /// <summary> /// 获得函数指针 /// </summary> /// <param name="lpFileName"> 包含需调用函数的 DLL 文件名 </param> /// <param name="lpProcName"> 调用函数的名称 </param> public void LoadFun(string lpFileName,string lpProcName) { // 取得函数库模块的句柄 hModule=LoadLibrary(lpFileName); // 若函数库模块的句柄为空,则抛出异常 if(hModule==IntPtr.Zero) throw(new Exception(" 没有找到 :"+lpFileName+"." )); // 取得函数指针 farProc = GetProcAddress(hModule,lpProcName); // 若函数指针,则抛出异常 if(farProc==IntPtr.Zero) throw(new Exception(" 没有找到 :"+lpProcName+" 这个函数的入口点 ")); } 6. 添加UnLoadDll及Invoke方法,Invoke方法也进行了重载: /// <summary> /// 卸载 Dll /// </summary> public void UnLoadDll() { FreeLibrary(hModule); hModule=IntPtr.Zero; farProc=IntPtr.Zero; } 以上就是ASP.NET调用动态链接库DLL的方法,希望对大家的学习有所帮助。 |
请发表评论