How can I make a Python Wheel from an existing native library?

后端 未结 2 650
谎友^
谎友^ 2020-12-23 21:55

Suppose I have a native shared library (.dll or .so), built independently of any Python mechanism, and a Python module using ctypes to interface to the library. Is there a w

相关标签:
2条回答
  • 2020-12-23 22:16

    Edit: Updated for newer versions of wheel as suggested by Thomas D.

    Here is a way. For an example, this uses libeay32.dll to expose an md5 package.

    The project structure is:

    MD5
    │   setup.py
    │
    └───md5
        __init__.py   
        libeay32.dll
    

    The setup.py is:

    from setuptools import setup, Distribution
    
    
    class BinaryDistribution(Distribution):
        def has_ext_modules(foo):
            return True
    
    
    setup(
        name='md5',
        version='1.0',
        description='MD5 Library',
        packages=['md5'],
        package_data={
            'md5': ['libeay32.dll'],
        },
        distclass=BinaryDistribution
    )
    

    A couple of things to note:

    1. The DLL is listed as package data so that it will be included in the wheel.
    2. A custom distclass is used that indicates this wheel has an extension module, and since the wheel is being built on Windows, that this is a win32 wheel.

    The Python ctypes code can load the DLL relative to itself (this code is in __init.py__):

    lib_path = os.path.join(os.path.dirname(__file__), 'libeay32.dll')
    lib = CDLL(lib_path)
    

    After having installed 'wheel' with pip, I can run python setup.py bdist_wheel to produce dist\md5-1.0-cp34-none-win32.whl. I happen to be using cpython 3.4, but if you want a universal wheel, you can add a setup.cfg like this one.

    Now I can create and activate a new virtual environment, pip install md5-1.0-cp34-none-win32.whl, and use my package:

    >>> import md5
    >>> md5.digest('hello')
    '8d11aa0625ce42cfe9429d5e93b5ab0a'
    
    0 讨论(0)
  • 2020-12-23 22:31

    Although the chosen answer was correct at the time of writing, this pull request broke this functionality.

    I think this answer correctly solves this problem in newer versions of the wheel package.

    (Would have added this as a comment, but lack the reputation needed.)

    0 讨论(0)
提交回复
热议问题