我通过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
我获得了一个完整的工作模块(我使用的一些函数需要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'])] )
并编辑了MANIFEST.in以保留源代码并避免类似本网站上类似问题的问题(即仅包括myExample.h和myExample.c)。然后我跑:
$python setup.py sdist
并通过“pip install”获得可安装的软件包。它似乎完成了(没有错误,没有警告),但是......它确实不工作。在这个可安装的模块(“_myExample.so” - 注意下划线,它似乎是distutils需要[也许它隐藏答案?])一些方法是不同的,一些方法是丢失的等等...因此我决定每次一步。只需编译:
$python setup.py build_ext
我已经遇到了同样的问题:最后的模块与通过开头解释的通常编译获得的模块不同。
总结:给定SWIG接口,传统编译或通过distutils编译它会产生不同的结果。怎么可能呢?我的setup.py错了吗?是否有另一种方法可以获得可安装pip的模块,而不依赖于distutils或setuptools(产生相同的问题)?
Ps:包装代码非常长,所以我不能遗憾地给出一个详细的列表,但我完全可以在需要时添加更多。例如,手动编译的接口成功包含“AdaptiveInterpolation”(工作正常),而distutil生成的接口具有“AdaptiveInterpolation_set”,“AdaptiveInterpolation_get”,或者有很多方法以“new_”开头(原来没有)码)。
答案 0 :(得分:2)
实际上,分发此类软件包有两种选择:bdist_wheel
和sdist
。
让我们从docs for distutils
获取SWIG的例子。
example.h文件
int fact(int n);
example.c
#include "example.h"
int fact(int n) {
if (n == 0) {
return 1;
}
else {
return n * fact(n - 1);
}
}
example.i
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
int fact(int n);
让我们构建一个SWIG接口,默认情况下生成example_wrap.c
。
swig -python example.i
Python Wheels是一种现代的分发格式,它简化了预构建软件包的分发(即软件包的用户不需要编译器,开发头等来安装它)。要使用它,我们需要setuptools
和wheel
(可以与pip
一起安装,或者从操作系统存储库sudo apt-get install python-wheel python-setuptools
安装)。
setup.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
)
您可以使用以下方式构建滚轮:
python setup.py bdist_wheel
在我的计算机上,它会生成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
要构建具有更好兼容性的轮子,您可以查看manylinux。
sdist
代表源代码分发,这意味着您的用户需要具有编译器和相关的开发依赖项。源分发使用以下内容构建:
python setup.py sdist
制作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