首页 文章

在Mac 10.8 64位上使用SWIG和distutils包装包含Python API的C代码失败

提问于
浏览
1

我一直试图将现有的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 回答

  • 0

    好吧,我不太明白你想要达到的目标,但我看到了一些不好的做法 . 例如,将 bilinearinterp 设置为静态,静态函数不会导出,只能在实现的同一模块中使用 . 我认为阅读一下SWIG设计思想会有所帮助 . 当然,这需要一些时间,但您将获得更广泛的视角,了解SWIG是什么和不具备的 .

相关问题