如何编写 setup.py 来安装 SWIG 构建的 python 扩展(xxx.so 文件)?

how to write setup.py to install python extention (xxx.so file) built by SWIG?

使用 SWIG 构建 python 扩展 (xxx.so) 比 distutils 更容易。您不需要编写 wrap.c 程序来包装您的原始 c 程序。所以我更喜欢使用 SWIG 而不是 Distutils。但是没有方法可以通过编写 setup.py 文件来自动安装扩展(xxx.so)。困扰了我很多天

为了把问题解释得更清楚,我用Step策略来表达清楚。

STEP 1: 有一个原始的C/C++代码。然后使用 SWIG 创建一个 Python 包装器。

第 2 步:使用 Distuils(编写 setup.py)或仅使用 gcc 命令行来创建 Python 扩展文件。 Python 扩展名是 xxx.so。显然,在这一步中,您可以使用Distuils将编译和安装结合起来。

第 3 步:通过编写 setup.py 安装 xxx.so Python 扩展。

我只是不知道如何编写 setup.py 安装 xxx.so Python 扩展的第 3 步。

有什么方法可以通过编写 setup.py 而不是使用 sys.path.append() 或 sys.path.insert() 方法来安装 python 扩展(xxx.so) ?

非常感谢您提供的任何答案!

最后还是尝试了STEP 2 编译安装结合的方法。它可以正常工作,但我的目的不是只使用 setup.py.

安装 _xxx.so Python 扩展

目录结构:

setup.py
src/
    libdemo/
        __init__.py
        LibHello.py
lib/
    palindrome.c   # original C code
    palindrome_wrap.c  # Python wrapper built by SWIG

setup.py代码:

#-*- coding:utf-8 -*-
import sys
import os
from setuptools import setup, find_packages, Extension

libPath = "lib"

moduleLibPalindrome = Extension(
      name = 'libdemo._palindrome', 
      sources = [os.path.join(libPath, 'palindrome_wrap.c'), 
            os.path.join(libPath, 'palindrome.c')]
)
setup (
      name = 'test_example',
      version = '0.1',
      author = "Hobart",
      description = "Install extension from original C/C++",
      packages= find_packages(where = 'src'),
      package_dir = {'':'src'},
      ext_modules=[moduleLibPalindrome]
)

结果检查:

>>> from libdemo import _palindrome
>>> dir(_palindrome)
['SWIG_PyInstanceMethod_New', '__builtins__', '__doc__', '__file__',      '__name__', '__package__', 'is_palindrome']
>>> _palindrome.is_palindrome('asddsa')
1
>>> 

C代码源文件和_palindrome.so文件显示为following。您可以下载并在您的计算机上进行实验。

Distutils 不是关于编写 扩展,而是关于编译和安装它们。 SWIG 可以帮助您为 C/C++ 代码创建 Python 包装器,但 不会 处理编译和安装它们。

因此,distutils 可以(并且应该)用于安装 SWIG 生成的扩展。请参阅 using distutils.

上的 SWIG 文档

编辑:我对你想要做什么感到有点困惑。通常,您会使用 distutils 来编译 安装您的扩展。这仍然可以通过调用

分两步完成
python setup.py build_ext
python setup.py install

但是,如果我理解正确的话,无论出于何种原因,您都有一个预编译的扩展(即 xxx.py 和 _xxx.so),并且希望仅使用例如distutils.

您可以为 distutils 使用 package_data 关键字,即以下 setup.py:

from distutils.core import setup
setup (name = 'xxx',
       version = '0.1',
       author = "Nobody",
       description = """Install precompiled extension""",
       py_modules = ["xxx"],
       packages=[''],
       package_data={'': ['_xxx.so']},
       )