使用C#或其他语言时经常会引用到DLL,分享一些学习笔记。 DLL(Dynamic Linkable Library),提供一些可以拿来用的变量,函数或类。 静态与动态链接库都是共享代码的方式,如果采用静态链接库,则无论愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。但是如果使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”引用和卸载这个与EXE独立的DLL文件。 1、DLL的编制与具体的编程语言及编译器无关 只要遵守约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用,像JAVA,C#调用C++编写的DLL。 在windows下的system32文件夹中可以看到许多.dll windows的大多数API都包含在这些DLL。像MessageBox函数就包含在user32.dll这个动态链接库中. 2、静态库编译 在VS下创建一个win32控制台应用程序,选择静态库,添加C++类,添加代码,完成后右击文件属性页,选择常规-输出目录-….\lib,选择平台工具集xp(保证兼容性)-编译,此时在lib文件夹中会生成文件。 在新的想要引用静态库的程序中,添加以上添加好代码的头文件.h,-右键进入属性页-选择C/C++-附加包含目录-(输入静态库头文件的目录)-链接器-常规-附加库目录….\lib-链接器-输入-附加依赖项-添加刚生成的.lib。 除了以上方法设置路径使用静态库,还可以在主程序中,添加头文件 #pragma comment(lib,'xxx.lib')//xxx代表需要引用的静态库 这样做的话就要把设置路径中的文件删除,防止多重定义。 3、DLL动态链接库编译 在VS下创建一个win32控制台应用程序,选择DLL(可以勾选导出符号,简便),看见新生成的dll.cpp等,dllmain.cpp作为自己用的动态库,可以不用过多关注,如果是多个程序的入口,则需要关注进程线程函数处理。添加代码,完成后右击文件属性页,选择常规-输出目录-….\dll,右键解决方案-属性-项目依赖项-选择主程序依赖于DLL。 右键主程序属性-链接器-常规-附加库目录-….. 常规-输出目录-….\bin;平台工具集xp;dll属性页-链接器-高级-导入库把
$(OutDir)改为..\..\lib; #pragma comment(lib,'xxx.lib')//xxx代表需要引用的静态库
使用.lib编译,程序不灵活,跨语言不方便,在函数前加extern “C”可以使函数不重载,告诉编译器是C语言,名字不会改动。这样的话把引用的头文件,库文件,引用函数都删掉。 加以下代码:
#include<windows.h>; typedef int(*DLLFUN)(void);生成一个函数指针 并在主函数main中加 HMODULE hdll = LoadLibrary(L'xx.dll');if(!hdll){return -1;}DLLFUN fun = GetProcAddress(hdll,'fndll');fun();FreeLibrary(hdll);//释放动态链接库 这种方法比较灵活,在很多项目都有用到,使扩展代码变得非常容易。 另外,看你要引用的dll是托管的还是非托管的。如果是托管的dll直接添加引用就可以,如果是非托管的有一段成熟代码可以拿来用 private object DllInvoke(string strDllFileName, string strNameSpace, string strClassName, string strDllProcName, object[] objArrayParams) { try { Assembly mAssembly = Assembly.LoadFrom(strDllFileName); Type[] mTypes = mAssembly.GetTypes(); foreach (Type mType in mTypes) { if (mType.Namespace == strNameSpace && mType.Name == strClassName) { MethodInfo mMethod = mType.GetMethod(strDllProcName); if (mMethod != null) { object mObject = Activator.CreateInstance(mType); return mMethod.Invoke(mObject, objArrayParams); } else { //MessageBox.Show('Load Report Dll File Failed!'); } } } } catch (Exception mEx) { MessageBox.Show(mEx.Message); } return null; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
strDllFileName,你引用的dll文件名 strNameSpace,名称空间,不用说了吧 strClassName,dll的类名 strDllProcName,接口过程名 objArrayParams,接口过程参数表
|