我一直在尝试将现有的C代码封装到Python模块中一段时间,并且我一直运行到经常性错误和失败的构建中......在广泛查看此论坛上的可用文档和帖子后,我想知道是否有人知道它为什么不起作用。使用SWIG包装Python API的C代码和distutils在Mac 10.8上失败64bits
我想使用stsci.imagemanip.interp2d.expand2d()函数,它由一个调用C函数的python脚本组成,它使用Python.h库。这在Mac 10.8 64位与Python 2.7下。
我是新的将C函数包装到Python中,我决定使用SWIG和distutils。
我的输入文件如下:
bilinearinterp.i
/* bilinearinterp.i */
%module bilinearinterp
%{
#define SWIG_FILE_WITH_INIT
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <stdio.h>
#include <Python.h>
#include <math.h>
#include <numpy/arrayobject.h>
#include "bilinearinterp.h"
%}
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
bilinearinterp.c
/* File: bilinearinterp.c */
#include <Python.h>
#include <stdio.h>
#include <math.h>
#include <numpy/arrayobject.h>
#include "bilinearinterp.h"
static void InterpInfo (float ai, int npts, int *i, float *p, float *q) {
/* arguments:
float ai i: independent variable in same units as i
int npts i: size of array within which *i is an index
int *i o: array index close to ai
float *p, *q o: weights for linear interpolation
*/
DO SOME CALCULATIONS
}
int unbin2d (float *a, float *b, int inx, int iny, int onx, int ony) {
/* arguments:
PyArrayObject *a i: input data
PyArrayObject *b o: output data
*/
DO SOME CALCULATIONS
CALL InterpInfo
return (1);
}
static PyObject * bilinearinterp(PyObject *obj, PyObject *args)
{
PyObject *input, *output;
PyArrayObject *dataa, *datab;
int inx, iny, onx, ony;
int status=0;
if (!PyArg_ParseTuple(args,"OO:bilinearinterp",&input,&output))
return NULL;
dataa = (PyArrayObject *)PyArray_ContiguousFromAny(input, PyArray_FLOAT, 1, 2);
datab = (PyArrayObject *)PyArray_ContiguousFromAny(output, PyArray_FLOAT, 1, 2);
inx = PyArray_DIM(input,0);
iny = PyArray_DIM(input,1);
onx = PyArray_DIM(output,0);
ony = PyArray_DIM(output,1);
status = unbin2d((float *)dataa->data,(float *)datab->data, inx, iny, onx, ony);
Py_XDECREF(dataa);
Py_XDECREF(datab);
return Py_BuildValue("i",status);
}
static PyMethodDef bilinearinterp_methods[] =
{
{"bilinearinterp", bilinearinterp, METH_VARARGS,
"bilinearinterp(input, output)"},
{0, 0} /* sentinel */
};
void initbilinearinterp(void) {
Py_InitModule("bilinearinterp", bilinearinterp_methods);
import_array();
}
bilinearinterp.h
/* File: bilinearinterp.H */
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
setup.py
#!/usr/bin/env python
from distutils.core import setup, Extension
bilinearinterp_module = Extension('_bilinearinterp',
sources = ['bilinearinterp_wrap.c','bilinearinterp.c'],
# Path to locate numpy/arrayobject.h
include_dirs=['/Library/Python/2.7/site-packages/numpy-override/numpy/core/include'])
setup (name = 'bilinearinterp',
version = '1.1',
author = "Space Telescope Science Institute - stsci_python",
description = """bilinear interpretation for 2D array extrapolation""",
ext_modules = [bilinearinterp_module],
py_modules = ["bilinearinterp"],
)
然后我运行在终端如下:
>>>swig -python bilinearinterp.i
>>>python setup.py build_ext --inplace
适当的文件被创建: _bilinearinterp.so bilinearinterp.py bilinearinterp.pyc bilinearinterp_wrap.c 以及包含一个build目录一些文件在里面。
当setup.py正在运行时,我收到警告,但似乎完成。 在各种测试中,我做了两个复发错误继续回来:
警告: “使用过时NumPy的API,通过#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION禁用”[-W#警告]
可能诱使关联到其他numpy的几个警告
警告:函数 'bilinearinterp' 具有内部连接,但没有定义[-Wundefined内部]静态的PyObject * bilinearinterp(的PyObject * OBJ,的PyObject *参数); bilinearinterp_wrap.c:2971:24:注意:这里使用的结果=(PyObject *)bilinearinterp(arg1,arg2);
然后在Python脚本中调用该模块时,我得到如下:
>>> from bilinearinterp import bilinearinterp as lininterp
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "bilinearinterp.py", line 28, in <module>
_bilinearinterp = swig_import_helper()
File "bilinearinterp.py", line 24, in swig_import_helper
_mod = imp.load_module('_bilinearinterp', fp, pathname, description)
ImportError: dlopen(./_bilinearinterp.so, 2): Symbol not found: _bilinearinterp
Referenced from: ./_bilinearinterp.so
Expected in: flat namespace
in ./_bilinearinterp.so
会有人有从那里错误可能源于现身的想法?
是从我使用SWIG还是从setup.py使用?
仅使用swig接口文件和C代码(不包括* .h文件)的另一种方法不起作用。基于the swig introduction chapter
bilinearinterp.i
/* bilinearinterp.i */
%module bilinearinterp
%{
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
%}
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
我编译使用:
>>>swig -python -o bilinearinterp_wrap.c bilinearinterp.i
>>>gcc -c -fpic bilinearinterp.c bilinearinterp_wrap.c
-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
-I/System//Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy/core/include
bilinearinterp_wrap.c:2955:19: warning: function 'bilinearinterp' has internal
linkage but is not defined [-Wundefined-internal]
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
^
bilinearinterp_wrap.c:2971:24: note: used here
result = (PyObject *)bilinearinterp(arg1,arg2);
^
1 warning generated.
>>>gcc -bundle -flat_namespace -undefined suppress bilinearinterp.o bilinearinterp_wrap.o -o _bilinearinterp.so
然后我仍然获得在Python解释器相同的导入错误。 难道这是由于我的numpy安装或我的gcc参数?
感谢
你在混合SWIG和Python C的扩展,这些是不同的东西。阅读http://www.swig.org/Doc2.0/Introduction.html#Introduction_nn8如何构建Python SWIG模块。 –
感谢您指出这一点!在介绍的例子中,只保留接口文件中的函数声明,我仍然遇到gcc的编译问题。请参阅上面的编辑。 –
在一个稍微不同的轨道上,你有没有考虑用Cython而不是SWIG来包装你的C代码?它可以为您节省很多您目前正在处理的这种麻烦。 – DaveP