Visual C ++:使用相对path链接另一个DLL的DLL

我有以下文件结构

C:\Application\application.exe C:\Application\plugins\myplugin\myplugin.dll C:\Application\plugins\myplugin\libs\utils.dll 

这里application.exe通过LoadLibrarydynamic加载myplugin.dll 。 请注意,我无法控制application.exe因为我只开发插件。

我想要的是通过相对path(理想情况下使用静态链接)使myplugin.dll加载libs\utils.dll 。 也就是说,我不想依赖于application.exe的位置。 我现在在安装myplugin时将C:\Application\plugins\myplugin\libsPATH环境variables中,但环境variables不是理想的解决scheme,我想避免这样做。

我希望我可以使用程序集和configuration文件来指定myplugin.dll的相对pathlibs\utils.dll 。 而我试过这个,但是无济于事。 然后我在StackOverflow上看到有人提到configuration文件只适用于应用程序(即可执行文件)。 但正如我上面所说,我无法控制application.exe 。 有没有解决这个看似简单的问题,我相信在Unix系统上可以通过rpaths解决?

您不能静态链接到DLL路径,相对或绝对。 PE导入表只包含文件名。 这就是为什么一个DLL搜索路径存在以查找DLL。

如果您想要控制utils.dll的加载位置,则必须动态加载它。 myplugin.dll可以使用传递到其DllMain()入口点的模块句柄使用GetmoduleeFileName()检索自己的路径。 然后,它可以从路径中删除文件名,将相对路径附加到路径,然后在需要时加载DLL(而不是在DllMain()本身内部,否则可能发生死锁/崩溃)。

有两种方法可以处理这个问题:

  1. 自己加载一切动态:

     #include <windows.h> #include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") HINSTANCE hThisDLL = NULL; HMODULE hUtils = NULL; typedef ReturnType __CallingConv (*DllFuncType)(Params); DllFuncType DllFunc = NULL; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { hThisDLL = hinstDLL; ... } return TRUE; } ... ReturnType CallDllFunc(Params) { if (!hUtils) { TCHAR szUtilsFileName[MAX_PATH] = {0}; GetmoduleeFileName(hThisDLL, szUtilsFileName, MAX_PATH); if (!PathRemoveFileSpec(szUtilsFileName)) { // do something... return ...; } if (!PathAppend(szUtilsFileName, TEXT("libs\\utils.dll"))) { // do something... return ...; } hUtils = LoadLibrary(szUtilsFileName); if (!hUtils) { // do something... return ...; } } if (!DllFunc) { DllFunc = (DllFuncType) GetProcAddress(hUtils, "DllFuncName"); if (!DllFunc) { // do something... return ...; } } return DllFunc(Params); } 
  2. (如果支持),那么你可以在运行时动态地指定DLL的文件名,但仍然静态链接到DLL函数本身(延迟加载机制将调用GetProcAddress()给你)。

     #include <windows.h> #include <shlwapi.h> #include <delayimp.h> #pragma comment(lib, "Delayimp.lib") #pragma comment(lib, "shlwapi.lib") HINSTANCE hThisDLL = NULL; FARPROC WINAPI DelayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli) { if ((dliNotify == dliNotePreLoadLibrary) && (strcmpi(pdli->szDll, "utils.dll") == 0)) { TCHAR szUtilsFileName[MAX_PATH] = {0}; GetmoduleeFileName(hThisDLL, szUtilsFileName, MAX_PATH); if (!PathRemoveFileSpec(szUtilsFileName)) { // do something... return NULL; } if (!PathAppend(szUtilsFileName, TEXT("libs\\utils.dll"))) { // do something... return NULL; } HMODULE hUtils = LoadLibrary(szUtilsFileName); return reinterpret_cast<FARPROC>(hUtils); } return NULL; } PfnDliHook __pfnDliNotifyHook2 = DelayLoadHook; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { hThisDLL = hinstDLL; ... } return TRUE; } ... ReturnType CallDllFunc(Params) { return DllFuncName(Params); }