如何将一个链接的DLL文件和一个pyd文件打包成一个自包含的pyd文件?

16

我正在使用Cython构建一个连接到DLL文件的Python模块。要成功导入我的模块,我需要在Windows搜索路径中有该DLL。否则,通常会出现以下错误消息:

ImportError: DLL load failed: 找不到指定的模块。

是否有一种方法可以将DLL直接打包到生成的pyd文件中,以便使分发变得更加容易?

一个这样的示例是OpenCV发行版,其中分发了一个(巨大的)pyd文件,这是Python绑定所需的唯一文件。


2
DLL可以放在扩展模块的相同目录中。Python使用LoadLibraryExLOAD_WITH_ALTERED_SEARCH_PATH来加载.pyd扩展。 - Eryk Sun
我正在寻找一种方法将两个文件合并为一个,无需在搜索路径中拥有DLL。 - toine
不确定,但我认为您可以使用ctypes.cdll或ctypes.windll首先加载库,然后它会找到它的实例,例如temp = ctypes.cdll.LoadLibrary('path_to_dll')。 或者,在您的pyd中,您可以访问os.environ()以在尝试加载DLL之前更新程序的PATH。 - Patrick Maupin
3
如果你有另一个DLL的源代码,你可以创建一个makefile将它们链接在一起。不确定是否有任何软件包可以让你重新链接。 - Patrick Maupin
这就是我正在寻找的重新链接方式:) - toine
1个回答

10

Python的打包和部署对我们许多人来说仍然是个痛点。并没有一种万能解决方案。以下是几种方法:


1. OpenCV构建方法

该方法在这里描述:https://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.html#bindings-basics

  

OpenCV使用位于modules/python/src2的一些Python脚本自动生成这些包装函数,从C++头文件中解析所需的static PyObject关键字。

基本上,它会解析头文件并生成static PyObject关键字,每当需要时就会生成。一旦适当地创建了头文件,它只需调用python setup即可。老实说,这种方法可能有效,但我不建议使用。

2. Makefile

如果您已经使用Makefile,请创建一个规则以相应地放置您的库。例如,从我的代码中:

  

setup.py

from distutils.core import setup, Extension
setup(name='sha1_hmac', version='1.0',  \
      ext_modules=[Extension('sha1_hmac',
                             library_dirs=['C:\MinGW\lib'],
                             sources= ['../tools/sha1.c','sha1_hmac.c'])])

Makefile

# The hmac generation used by the webserver is done
# using the sha1.c implementation. There is a binding needed to
# glue the C code with the python script
libsha1_hmac:
ifeq ($(OS), Windows_NT)
    $(PYTHON) setup.py build --compiler=mingw32
else
    $(PYTHON) setup.py install --home=$(CURDIR)
endif

.PHONY: webserver
webserver:  libsha1_hmac
ifeq ($(OS), Windows_NT)
    mv $(shell find build -type f -name "sha1*.pyd") $(LIB)
else
    mv -f $(shell find $(LIB)/python -type f -name "sha1*.so") $(LIB)
endif
    $(PYTHON) hmac_server.py

3. 现代化的部署工具

现在有几种新的部署 Python 应用程序的工具,即 wheels,看起来越来越受欢迎。虽然我不使用它,但它似乎可以解决您的捆绑问题:

一旦它被 wheeled,您可以像这样安装它:pip install some-package.whl


openCV的构建方法可以生成我需要的1个pyd文件(并且可以访问源代码)。对于第二种方法,我不知道是否可以将winDLL作为源代码。在我的情况下,它们在libraries/library_dirs中。对于第三种方法,似乎DLL将被分发,但不会合并到最终的pyd文件中。 - toine
你有DLL源代码的访问权限吗?还是像user32.dll一样只是链接它?只有第一种情况适用于OpenCV的方法。 - lucasg
在我的特殊情况下,我确实可以访问源代码,并且将所有内容重新构建到一个唯一的构建项目中是可行的。然而,如果没有访问源代码的权限,我正在寻找解决方案。 - toine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接