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

时间:2016-06-30 14:07:25

标签: python swig setup.py python-extensions

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

为了解释更易于理解的问题,我使用步骤策略来说清楚。

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

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

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

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

有没有办法通过编写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。你可以在电脑上下载并做实验。

1 个答案:

答案 0 :(得分:4)

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。

您可以将package_data关键字用于distutils,即以下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']},
       )