在 Linux/GCC 上,我可以使用 -rpath 标志来更改共享库的可执行文件搜索路径,而无需使用环境变量进行调整。
这也可以在 Windows 上完成吗?据我所知,dll 总是在可执行文件的目录和 PATH 中搜索。
我的场景:我想根据共享库的属性(32/64位/调试/发布)将共享库放入位置,而不考虑唯一的名称。在 Linux 上,这可以通过 rpath 轻松完成,但我还没有找到在 Windows 上执行此操作的任何方法。
感谢您的任何提示!
遗憾的是,没有与 RPATH 直接类似的东西。有许多替代的可能性,每一种都可能以自己特殊的方式不适合您。
鉴于您无论如何都需要为每种构建风格使用不同的 exe,以避免运行时库冲突,因为您可能会猜测最简单的方法是将每个 exe 与每组 DLL 放在同一文件夹中。
正如您还提到的,最通用的方法是通过使用批处理文件引导 exe 来更改 PATH 变量。
您可以在运行程序之前更改当前工作目录到所需的 DLL 文件夹。
您可以在 exe 中使用函数 SetDllDirectory 或 AddDllDirectory。这可能是最接近 RPATH 的,但仅适用于 WinXP SP1 或更高版本。
如果您愿意更改每个 exe 风格的文件名,可以使用“App Paths”注册表项。每个 exe 都需要一个唯一的文件名。
“隔离的应用程序”是一种嵌入描述 DLL 依赖关系的 XML 清单的机制。
我发现的最好的技巧就是这里描述的:
https://devblogs.microsoft.com/oldnewthing/20170126-00/?p=95265
使用起来很麻烦,但它比 UNIX 更强大
-rpath
,因为它允许动态生成路径,同时保留隐式链接的所有好处。
我在这里使用它: https://github.com/mmomtchev/meson-xpack/blob/main/wrappers/wrapper.c#L8-L35
这是完整的示例:
HMODULE LoadPython() {
static char path[4096];
const char *root;
snprintf(path, 4096, "%s/%s/%s", root, PYTHON_PATH, PYTHON_DLL);
return LoadLibraryA(path);
}
FARPROC WINAPI delayHook(unsigned dliNotify, PDelayLoadInfo pdli) {
if (dliNotify == dliNotePreLoadLibrary && strcmp(pdli->szDll, PYTHON_DLL) == 0) {
return (FARPROC)LoadPython();
}
return NULL;
}
ExternC const PfnDliHook __pfnDliNotifyHook2 = delayHook;
ExternC const PfnDliHook __pfnDliFailureHook2 = delayHook;
然后将您的程序链接到
/DELAYLOAD:"python312.dll"
普通的旧C,在链接器级别启用DLL的延迟加载,然后注册一个拦截加载的钩子。