分享

动态链接库DLL使用学习笔记

 老来乐65 2019-09-28

使用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代表需要引用的静态库
  • 1

这样做的话就要把设置路径中的文件删除,防止多重定义。

3、DLL动态链接库编译
在VS下创建一个win32控制台应用程序,选择DLL(可以勾选导出符号,简便),看见新生成的dll.cpp等,dllmain.cpp作为自己用的动态库,可以不用过多关注,如果是多个程序的入口,则需要关注进程线程函数处理。添加代码,完成后右击文件属性页,选择常规-输出目录-….\dll,右键解决方案-属性-项目依赖项-选择主程序依赖于DLL。
右键主程序属性-链接器-常规-附加库目录-…..
常规-输出目录-….\bin;平台工具集xp;dll属性页-链接器-高级-导入库把
$(OutDir)改为..\..\lib;

#pragma comment(lib,'xxx.lib')//xxx代表需要引用的静态库
  • 1
  • 2

使用.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);//释放动态链接库
  • 1
  • 2
  • 3
  • 4
  • 5

这种方法比较灵活,在很多项目都有用到,使扩展代码变得非常容易。
另外,看你要引用的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,接口过程参数表

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多