从.pyd模块调用LoadLibrary失败但Python直接加载DLL成功问题
核心原因
Windows错误码126对应ERROR_MOD_NOT_FOUND,此处加载失败并非全路径指定的MyClass.dll本身缺失,而是MyClass.dll依赖的、存放在同目录下的其他DLL无法被定位。
Windows默认DLL搜索逻辑不会自动将传入LoadLibraryW的目标DLL所在目录加入依赖检索路径。直接在pyd模块内调用LoadLibraryW加载全路径的MyClass.dll时,系统可以找到MyClass.dll本体,但解析其同目录依赖时只会按默认顺序检索以下位置:
- python.exe所在目录
- Windows系统目录(System32、SysWOW64等)
- Windows根目录
- 进程当前工作目录
- PATH环境变量中列出的路径
上述路径列表不包含C:/full/path/to/library/,自然无法找到MyClass.dll的同目录依赖,最终返回126错误。
ctypes加载DLL时内部做了额外处理:调用系统加载接口前会临时将待加载DLL的所在目录加入进程DLL搜索路径,因此可以顺利解析同目录依赖完成加载。同时Windows存在已加载DLL全局缓存机制,同路径的DLL只要被进程加载过一次,后续任意模块调用LoadLibraryW加载同路径DLL时,系统会直接返回缓存的模块句柄,不会重新执行依赖解析流程,这就是后续pyd内的加载调用能成功的原因。
修复方案
- 替换加载接口:使用
LoadLibraryExW替代LoadLibraryW,传入LOAD_WITH_ALTERED_SEARCH_PATH标志,系统会自动将目标DLL所在目录设为依赖检索优先目录,无需手动修改搜索路径即可找到同目录依赖,示例代码:
HMODULE lib = LoadLibraryExW( L"C:/full/path/to/library/MyClass.dll", nullptr, LOAD_WITH_ALTERED_SEARCH_PATH );
- 手动临时修改搜索路径:加载MyClass.dll前调用
SetDllDirectoryW将DLL所在目录加入检索路径,加载完成后可恢复默认配置:
SetDllDirectoryW(L"C:/full/path/to/library/"); HMODULE lib = LoadLibraryW(L"C:/full/path/to/library/MyClass.dll"); SetDllDirectoryW(nullptr); // 恢复默认搜索路径配置
- 永久添加搜索目录:如果需要长期从该目录加载依赖,可以在pyd模块初始化阶段调用
AddDllDirectory将目标目录加入进程自定义DLL检索列表,后续加载操作会自动从该目录查找依赖。
内容的提问来源于stack exchange,提问作者Osyotr
相关产品推荐
相关产品推荐

