2013-12-07 34 views
1

我一直在尝试将现有的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正在运行时,我收到警告,但似乎完成。 在各种测试中,我做了两个复发错误继续回来:

  1. 警告: “使用过时NumPy的API,通过#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION禁用”[-W#警告]

    可能诱使关联到其他numpy的几个警告

  2. 警告:函数 '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参数?

感谢

+0

你在混合SWIG和Python C的扩展,这些是不同的东西。阅读http://www.swig.org/Doc2.0/Introduction.html#Introduction_nn8如何构建Python SWIG模块。 –

+0

感谢您指出这一点!在介绍的例子中,只保留接口文件中的函数声明,我仍然遇到gcc的编译问题。请参阅上面的编辑。 –

+0

在一个稍微不同的轨道上,你有没有考虑用Cython而不是SWIG来包装你的C代码?它可以为您节省很多您目前正在处理的这种麻烦。 – DaveP

回答

0

嗯,我不太明白你想达到什么样的,但我看到了一些不好的做法。例如,您将bilinearinterp设置为静态,并且静态函数不会导出,只能在实现的相同模块中使用。我认为读一下SWIG设计思路会有所帮助。可以肯定的是,这需要一段时间,但是你会对SWIG是什么以及不能做什么有更广泛的认识。

+0

这让我觉得我可能在方法上有一点错误。由于我对Python包装C代码的理解有限,因此我花了一段时间才明白,我想要使用的C代码已经使用Python.h库和numpy C-API进行了包装。所以我想要做的是添加一个名为bilinear interp的python模块,它使用bilinearinterp.c。自行使用distutils应该做到这一点,不应该有需要swig。我对这种新方法适用吗? –