Distutils以(工作)SWIG扩展名失败

8 python setuptools setup.py

我通过SWIG在python模块中包装一个C库,这里称为"myExample".如果我编译:

$swig -python myExample.i
$gcc -c myExample_wrap.c -I /usr/lib/python2.7 -fPIC -std=c99
$ld -shared myExample_wrap.so -llapacke -o _myExample.so
Run Code Online (Sandbox Code Playgroud)

我获得了一个完整的工作模块(我使用的一些函数需要liblapacke).现在我想通过"pip install"使这个模块可以安装.

根据distutils部分(https://docs.python.org/2.7/distutils/setupscript.html),我编写了我的setup.py文件:

from distutils.core import setup, Extension
setup(name='myExample',
version='0.1',
ext_modules=[Extension('_myExample',['myExample.i'], libraries= ['lapacke'])] )
Run Code Online (Sandbox Code Playgroud)

并编辑了MANIFEST.in以保留源代码并避免类似本网站上类似问题的问题(即仅包括myExample.h和myExample.c).然后我跑:

$python setup.py sdist
Run Code Online (Sandbox Code Playgroud)

并通过"pip install"获得可安装的软件包.它似乎做(没有错误,没有警告),但是......它并没有正常工作.在这个可安装的模块("_myExample.so" - 注意下划线,它似乎是distutils需要[也许它隐藏答案?])一些方法是不同的,一些方法是丢失的等等...因此我决定每次一步.通过编译:

$python setup.py build_ext
Run Code Online (Sandbox Code Playgroud)

我已经遇到了同样的问题:最终模块与通过开头解释的通常编译获得的模块不同.

总结:给定SWIG接口,传统编译或通过distutils编译它会产生不同的结果.怎么可能呢?我的setup.py错了吗?是否有另一种方法可以获得可安装pip的模块,而不依赖于distutils或setuptools(产生相同的问题)?

Ps:包装代码很长,所以我不能遗憾地给出一个详细的列表,但我完全可以在需要时添加更多.例如,手动编译的接口成功包含"AdaptiveInterpolation"(工作正常),而distutil生成的接口具有"AdaptiveInterpolation_set","AdaptiveInterpolation_get",或者有很多方法以"new_"开头(原来不存在)码).

saa*_*aaj 3

实际上,有两种分发此类包的选项:bdist_wheelsdist

让我们以文档distutils中的 SWIG 为例。

示例.h

int fact(int n);
Run Code Online (Sandbox Code Playgroud)

示例.c

#include "example.h"

int fact(int n) {
    if (n == 0) {
        return 1;
    }
    else {
        return n * fact(n - 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

示例.i

%module example

%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}

int fact(int n);
Run Code Online (Sandbox Code Playgroud)

让我们构建一个 SWIG 接口,默认情况下会生成example_wrap.c.

swig -python example.i 
Run Code Online (Sandbox Code Playgroud)

车轮

Python Wheels是一种现代的分发格式,它简化了预构建包的分发(即包的用户不需要编译器、开发头文件等来安装它)。要使用它,我们需要setuptoolswheel(可以通过操作系统存储库安装pip或从操作系统存储库安装sudo apt-get install python-wheel python-setuptools)。

安装程序.py

from setuptools import setup, Extension


setup(
  name = 'example',
  version = '0.1',
  author = 'SWIG Docs',
  description = 'Simple swig example from docs',
  ext_modules = [
    Extension('_example', sources = ['example_wrap.c', 'example.c'])],
  py_modules = ['example'],
  package_data = {'': ['example.h']}  # needed for sdist
)
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法构建轮子:

python setup.py bdist_wheel
Run Code Online (Sandbox Code Playgroud)

在我的机器上它生成了example-0.1-cp27-cp27mu-linux_x86_64.whl我可以安装pip并测试的东西python -c 'import example; print(example.fact(5))'。请注意文件名。它编码兼容的Python版本、ABI和平台。以下是内容列表 ( unzip -l ...)。

Archive:  example-0.1-cp27-cp27mu-linux_x86_64.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
     2609  2018-02-24 11:06   example.py
    70968  2018-02-24 13:31   _example.so
       10  2018-02-24 14:58   example-0.1.dist-info/DESCRIPTION.rst
      290  2018-02-24 14:58   example-0.1.dist-info/metadata.json
       17  2018-02-24 14:58   example-0.1.dist-info/top_level.txt
      105  2018-02-24 14:58   example-0.1.dist-info/WHEEL
      193  2018-02-24 14:58   example-0.1.dist-info/METADATA
      617  2018-02-24 14:58   example-0.1.dist-info/RECORD
---------                     -------
    74809                     8 files
Run Code Online (Sandbox Code Playgroud)

例如,要构建具有更好兼容性的轮子,您可以查看Manylinux

来源

sdist代表源代码分发,这意味着您的用户将需要有一个编译器和相关的开发依赖项。源代码分发是通过以下方式构建的:

python setup.py sdist
Run Code Online (Sandbox Code Playgroud)

产生的example-0.1.tar.gz内容包含(tar -tf ...):

example-0.1/
example-0.1/example.c
example-0.1/PKG-INFO
example-0.1/example.egg-info/
example-0.1/example.egg-info/PKG-INFO
example-0.1/example.egg-info/dependency_links.txt
example-0.1/example.egg-info/top_level.txt
example-0.1/example.egg-info/SOURCES.txt
example-0.1/setup.cfg
example-0.1/example.py
example-0.1/setup.py
example-0.1/example_wrap.c
example-0.1/example.h
Run Code Online (Sandbox Code Playgroud)