我有proj1.dll
依赖于另一个DLL proj2.dll
。我在编译VS2013中的proj1.dll
时编译了编译器输出的导入库proj2.dll
。我还导出了我感兴趣的公共函数。所以现在我有两个独立的DLL,它们都符合' cdll'标准。
我想在Python中使用proj1.dll
,但我遇到了以下问题:
import ctypes
# Crashes saying no entry point for "some_func" in proj2.dll
ctypes.cdll.LoadLibrary("C:\myfolder\proj1.dll")
ctypes.cdll.LoadLibrary("C:\myfolder\proj2.dll") # Loads fine
ctypes.cdll.LoadLibrary("C:\myfolder\proj1.dll") # Loads fine if proj2 is loaded first
当我将proj2
构建为静态库并在proj1
中与其链接时,从Python调用此DLL之前有效。这两个DLL存在于同一文件夹中。我甚至尝试将文件夹的路径添加到我的PATH环境变量中,以查看这是否是一个路径问题,但没有任何改变。
我假设Windows会加载proj1.dll
然后加载dll的依赖项。我错了吗?调用者(Python)是否必须首先加载依赖项DLL?任何人都知道为什么会这样吗?
答案 0 :(得分:1)
您需要确保您的环境路径包含依赖项的路径。这会起作用。
import os
from ctypes import *
path_to_deps = "C:\\myfolder"
os.environ['PATH'] = path_to_deps + os.pathsep + os.environ['PATH']
d = CDLL("C:\myfolder\proj2.dll")
更新:
在python 3.8 update notes中已添加了呼叫os.add_dll_directory(path)
,该呼叫用于指定要搜索的dll目录。
答案 1 :(得分:0)
也许您的项目需要更改构建设置。
答案 2 :(得分:0)
列出[Python 3.Docs]: ctypes - A foreign function library for Python。
考虑到提出问题的时间,可以排除 Python 3.8 (但[SO]: PyWin32 and Python 3.8.0 (@CristiFati's answer)可能仍然很有趣)。
对于加载 .dll 的泛型,[SO]: Python Ctypes - loading dll throws OSError: [WinError 193] %1 is not a valid Win32 application (@CristiFati's answer)可能包含有用的信息。
现在,问题不完全是 MCVE 或 REPREX ([SO]: How to create a Minimal, Reproducible Example (reprex (mcve))),但我认为如果是这样,答案可能是很明显,因此不需要这个问题:)
错误为 ERROR_PROC_NOT_FOUND ( 127 , 0x7F )。
注意: .dll 仅在其所有依赖项都已成功(递归)加载后才加载。如果其中一个依赖项失败,则故障会一直传播到顶部,并且(原始) .dll 加载会因该错误而失败。
这2种情况会自动发生:
成功:
proj1 试图加载
结果,此步骤(#2。)也成功
失败:
从上面的内容,我们只能得出结论,在%PATH%中某处 proj2.dll ,并且该文件正在由 OS 加载 proj1.dll 时。
它不是 C:\ myfolder \ proj2.dll 。可能是较旧的版本,没有导出所需的功能,或者是另一个完全不相关的版本。
我设法通过2个简单的(相关).em.dll 和一个 .exe 重现崩溃(如果需要,我还将发布代码):< / p>
(最简单的)解决方案是将 proj2.dll (右)目录中的“ C:\ myfolder ”添加到%PATH% ,然后再加载 proj1.dll 。选中[MS.Docs]: Dynamic-Link Library Search Order,并牢记以下几个方面:
您必须在错误的 dir 之前添加(或更妙的是,从错误的 dir 中删除错误的 dir 总计%PATH%)。要检查它在哪里,请使用(在 cmd 中)终端:
where proj2.dll
由于我不知道错误的 .dll dir 位置在%PATH%中,因此添加了正确的位置在%PATH%开头的 .dll dir 将是 OK 。就个人而言,我不认为在 Win 系统目录之前添加目录是一个好习惯
无论如何,都可以执行%PATH%更改:
在启动 Python 之前:
set PATH=C:\myfolder;%PATH%
来自 Python 本身:
os.environ["PATH"] = "C:\myfolder;" + os.environ["PATH"]
对于 Python 3.8 ,在答案的开头检查相关的 URL
Dependency Walker是用于(静态) .dll 依赖项检查的出色工具。