我一直试图将现有的C代码包装到Python模块中一段时间了,我一直在遇到经常性的错误和失败的构建......在广泛查看本论坛上的可用文档和帖子后,我想知道如果有人知道它为什么不起作用 .
我想使用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以及包含其中一些文件的构建目录 .
当setup.py正在运行时,我收到警告,但它似乎已完成 . 在各种测试中,我做了两个反复出现的错误不断回来:
- 警告:“使用已弃用的NumPy API,通过#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION”[-W#warnings]禁用它
这可能会导致与numpy相关的其他几个警告
- 警告:函数'bilinearinterp'有内部链接但未定义[-Wundefined-internal] static PyObject * bilinearinterp(PyObject * obj,PyObject * args); bilinearinterp_wrap.c:2971:24:注意:此处使用result =(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参数?
谢谢
1 回答
好吧,我不太明白你想要达到的目标,但我看到了一些不好的做法 . 例如,将
bilinearinterp
设置为静态,静态函数不会导出,只能在实现的同一模块中使用 . 我认为阅读一下SWIG设计思想会有所帮助 . 当然,这需要一些时间,但您将获得更广泛的视角,了解SWIG是什么和不具备的 .