今天在开发的过程中,需要用到动态库里的一些接口,又不希望全部载入,在这过程中使用LoadLibrary加载dll时,出现问题,特此记录一下自己怎么解决的思路。
目录
先介绍一下这几个函数为以下错误分析做准备
GetProcAddress 函数
GetProcAddress 函数
FreeLibrary 函数
一、文件路径错误
二、编码传值问题
三、动态库不匹配
四、排错函数的使用
1、用VS自带的命令,找到下图的这个双击打开
2、如下图,执行了后,在你设置的对应路径去查找这个文件
3、下图就是输出的文件,进进去查看就知道是否依赖了其它dll动态库
4、当有依赖其它动态库,怎么办,我现在介绍另一个函数
LoadLibraryEx
先介绍一下这几个函数为以下错误分析做准备
GetProcAddress 函数
[格式]:
function LoadLibrary(LibFileName : PChar): Thandle;
[功能]:加载由参数 LibFileName 指定的 DLL 文件。
[说明]:参数 LibFileName 指定了要装载的 DLL 文件名,如果 LibFileName 没有包含一个路径,系统将按照:当前目录、Windows 目录、Windows 系统目录、包含当前任务可执行文件的目录、列在 PATH 环境变量中的目录等顺序查找文件。
如果函数操作成功,将返回装载 DLL 库模块的实例句柄,否则,将返回一个错误代码,错误代码的定义如引文[1]所示。
GetProcAddress 函数
[格式]:
function GetProcAddress(Module:Thandle; ProcName:PChar): TfarProc;
[功能]:返回参数 Module 指定的模块中,由参数 ProcName 指定的过程或函数的入口地址。
[说明]:参数 Module 包含被调用函数的 DLL 句柄,这个值由 LoadLibrary 返回, ProcName
是指向含有函数名的以 nil 结尾的字符串指针,或者可以是函数的次序值,但大多数情况下,用函数名是一种更稳妥的选择。如果该函数执行成功,则返回 DLL 中由参数 ProcName 指定的过程或函数的入口地址,否则返回 nil 。
FreeLibrary 函数
[格式]:
procedure FreeLibrary(Module: Thandle);
[功能]:将由参数 Module 指定的 DLL 文件从内存中卸载 1 次。
[说明]:Module 为 DLL 库的句柄。这个值由 LoadLibrary 返回。由于 DLL 在内存中只装载一次,因此调用 FreeLibrary 首先使 DLL 的引用计数减 1,如果计数减为 0 则卸载该 DLL。
[注意]:每调用一次 LoadLibrary 函数就应调用一次 FreeLibrary 函数,以保证不会有多余的库模块在应用程序结束后仍留在内存中,否则导致内存泄漏。
一、文件路径错误
传入LoadLibrary的路径有问题,仔细排查路径是否错误。可以先用绝对路径试一试,再尝试能不能链接到。
二、编码传值问题
传入LoadLibrary的参数必须为LPCWTR类型,当你传入的类型不匹配可能发生错误,仔细核对你当前的编码问题。
三、动态库不匹配
这里的动态库指的,你的程序64位进程调用了32位dll动态库。
四、排错函数的使用
当你运行完这条语句,再下面再次运行std::cout << GetLastError();语句,用来返回错误码,根据错误码查找对应的文档,判断对应的错误。
LoadLibrary(path);
std::cout << GetLastError();
一般而言错误代码为"126",查找对应的错误代码表,发现错误"126"是指"找不到指定的模块",这时候就分析了,为什么会出现这种错误,经过分析,发现如果你的dll动态库里面依赖了其它dll动态库应该用另一个接口LoadLibraryEx,这里给出分析dll动态库怎么找到它对应依赖的dll动态库的方法。
1、用VS自带的命令,找到下图的这个双击打开
2、如下图,执行了后,在你设置的对应路径去查找这个文件
命令格式:
dumpbin -imports 路径\MyDll.dll > 路径\result.txt (>指的是这个dll依赖查看文件输出到哪个路径)
3、下图就是输出的文件,进进去查看就知道是否依赖了其它dll动态库
4、当有依赖其它动态库,怎么办,我现在介绍另一个函数
LoadLibraryEx
若DLL不在调用方的同一目录下,可以用LoadLibrary(L"DLL绝对路径")加载。但若调用的DLL内部又调用另外一个DLL,此时调用仍会失败。解决办法是用 LoadLibraryEx,通过指定 LOAD_WITH_ALTERED_SEARCH_PATH,让系统DLL搜索顺序从DLL所在目录开始。
LoadLibraryEx("DLL绝对路径", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);