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 里的类和函数达到我们的目
的。为了以后使用方便及实现代码的复用,我们可以编写一个类。 1) dld 类的编写:
1.
“
打开项目 Tzb”
“
,打开类视图,右击 Tzb”
“
”
,选择 添加 -->“ ”
“
类 ,类名设置为 dld”,即
dynamic loading dll 的每个单词的开头字母。
2. 添加所需的命名空间及声明参数传递方式枚举:
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)