[英]Wrapping C code including Python API using SWIG and distutils fails on Mac 10.8 64bits
I have been trying to wrap an existing C code into a Python module for some time now and I keep running into recurrent errors and a failed build... After an extensive look at the available documentation and posts on this forum I would like to know if someone has an idea why it is not working. 我一直在尝试将现有的C代码包装到Python模块中一段时间,并且不断遇到反复出现的错误和构建失败的情况。在仔细阅读了本论坛上的可用文档和帖子后,我想知道如果有人知道为什么它不起作用。
I would like to use the stsci.imagemanip.interp2d.expand2d() function which consists of a python script calling a C function which uses the Python.h library. 我想使用stsci.imagemanip.interp2d.expand2d()函数,该函数包含一个调用C函数的python脚本,该C函数使用Python.h库。 This under Mac 10.8 64bits with Python 2.7. 在Mac 10.8 64位和Python 2.7下。
I am new to wrapping C functions to Python and I decided to use SWIG and distutils. 我是将C函数包装到Python的新手,因此决定使用SWIG和distutils。
My input files are the following: 我的输入文件如下:
bilinearinterp.i 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 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 bilinearinterp.h
/* File: bilinearinterp.H */
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
setup.py 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"],
)
Then I run the following in Terminal: 然后在终端中运行以下命令:
>>>swig -python bilinearinterp.i
>>>python setup.py build_ext --inplace
The appropriate files are being created: _bilinearinterp.so bilinearinterp.py bilinearinterp.pyc bilinearinterp_wrap.c As well as a build directory containing some files in it. 正在创建适当的文件:_bilinearinterp.so bilinearinterp.py bilinearinterp.pyc bilinearinterp_wrap.c以及其中包含一些文件的构建目录。
I get warnings when setup.py is running but it seems to complete. 我在运行setup.py时收到警告,但似乎已完成。 Over the various tests I did two recurrent errors keep coming back: 在各种测试中,我反复出现了两个反复出现的错误:
warning: "Using deprecated NumPy API, disable it by #defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-W#warnings] 警告:“使用已弃用的NumPy API,通过#定义NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION来禁用它” [-W#warnings]
Which may induces several other warnings associated to numpy 这可能会引发与numpy相关的其他一些警告
warning: function 'bilinearinterp' has internal linkage but is not defined [-Wundefined-internal] static PyObject * bilinearinterp(PyObject *obj, PyObject *args); 警告:函数'bilinearinterp'具有内部链接,但未定义[-Wundefined-internal]静态PyObject * bilinearinterp(PyObject * obj,PyObject * args); bilinearinterp_wrap.c:2971:24: note: used here result = (PyObject *)bilinearinterp(arg1,arg2); bilinearinterp_wrap.c:2971:24:注意:此处使用结果=(PyObject *)bilinearinterp(arg1,arg2);
Then when calling the module in a python script I get the following: 然后,当在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
Would someone have an idea from where the error could be coming from? 会有人知道错误可能来自何处吗?
Is it from my usage of SWIG or from setup.py? 是我使用SWIG还是setup.py?
Another approach with only a swig interface file and the C code (without including the *.h file) does not work. 仅带有Swig接口文件和C代码(不包括* .h文件)的另一种方法不起作用。 Based on the swig introduction chapter 基于swig介绍章节
bilinearinterp.i bilinearinterp.i
/* bilinearinterp.i */
%module bilinearinterp
%{
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
%}
static PyObject * bilinearinterp(PyObject *obj, PyObject *args);
And I compile using: 我使用以下命令进行编译:
>>>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
Then I still get the same import error in the python interpreter. 然后我仍然在python解释器中得到相同的导入错误。 Could it be due to my numpy installation or my gcc arguments? 可能是由于numpy安装或gcc参数引起的吗?
Thanks 谢谢
Well, I don't quite understand what you are trying to achieve, but I see some bad practices. 好吧,我不太了解您要达到的目标,但是我看到了一些不良做法。 For example, you make bilinearinterp
everywhere static, and static functions are not exported and only can be used in the same module where implemented. 例如,您使bilinearinterp
到处都是静态的,并且静态函数不会导出,只能在实现的同一模块中使用。 I think it would be helpful to read a bit about SWIG design ideas. 我认为阅读一下SWIG设计思想会有所帮助。 For sure it will take a some time, but you will get a broader perspective of what SWIG is and isn't capable of. 当然,这将需要一些时间,但是您将获得SWIG功能的更广阔视野。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.