用swig和python扩展全局c变量数组



我在c中有一个全局变量数组,我想把它拉到python中。我在使用varout类型图时遇到了困难:

/* example.c */
int foo[] = {0, 1};

这是一个非常普通的界面:

/* example.i */
%module example
%{     
 extern int foo[2];
%}
%typemap(varout) int foo[] {
  int i;
  //$1, $1_dim0, $1_dim1
  $result = PyList_New($1_dim0);
  for (i = 0; i < $1_dim0; i++) {
    PyObject *o = PyInt_FromLong((double) $1[i]);
    PyList_SetItem($result,i,o);
  }
}
%include "example.c"

当我尝试用以下SConstruct构建它时:

import distutils.sysconfig
env = Environment(SWIGFLAGS='-python -shadow -Wall'.split(),
                  CPPPATH=[distutils.sysconfig.get_python_inc()],
                  SHLIBPREFIX="")
env.SharedLibrary('_example.so', ['example.c', 'example.i'])

$1_dim0特殊变量未填充,导致example_wrap.c中出现以下不可编译代码:

SWIGINTERN PyObject *Swig_var_foo_get(void) {
  PyObject *pyobj = 0;
  {
    int i;
    //foo, , foo_dim1
    pyobj = PyList_New();
    for (i = 0; i < ; i++) {
      PyObject *o = PyInt_FromLong((double) foo[i]);
      PyList_SetItem(pyobj,i,o);
    }
  }
  return pyobj;
}

很明显,类型映射匹配已经发生,但数组的维度缺失。我错过了什么?对尺寸进行硬编码确实有效。

一般来说,有没有办法用swig扩展全局cvar变量

$ swig -version
SWIG Version 2.0.4
Compiled with g++ [i686-pc-linux-gnu]
Configured options: +pcre
Please see http://www.swig.org for reporting bugs and further information

您的varout类型映射即将实现。你需要做两个小改动:

  1. 您需要将尺寸ANY添加到int foo[]类型映射:

    %typemap(varout) int foo[ANY] {
      int i;
      //$1, $1_dim0, $1_dim1
      $result = PyList_New($1_dim0);
      for (i = 0; i < $1_dim0; i++) {
        PyObject *o = PyInt_FromLong((double) $1[i]);
        PyList_SetItem($result,i,o);
      }
    }
    

    这可以确保您的类型映射与(任何)已知大小的数组匹配,而不仅仅等同于int *foo

  2. 您需要修改example.c以使foo的大小更清晰。它是合法和正确的C,但除非你碰巧是一个完整的C编译器,否则很难推断数组的大小。更改为:

    int foo[2] = {0, 1};
    

    足以确保它与CCD_ 10类型映射匹配。

有了这两个更改,生成的代码就如您所希望的那样工作:

SWIGINTERN PyObject *Swig_var_foo_get(void) {
  PyObject *pyobj = 0;
  {
    int i;
    //foo, 2, foo_dim1
    pyobj = PyList_New(2);
    for (i = 0; i < 2; i++) {
      PyObject *o = PyInt_FromLong((double) foo[i]);
      PyList_SetItem(pyobj,i,o);
    }
  }
  return pyobj;
}

就是在我的机器上通过这些更改生成的内容。

对于像我这样思考如何处理非简单类型数组的人来说,这里有一种方法:

非简单类型:

typedef struct {
    int a;
    float b;
} Foo;

和一个全局阵列:

extern Foo *foov[40];
%typemap(varout) Foo *foov[ANY] {
    int i;
    $result = PyList_New($1_dim0);
    for (i = 0; i < $1_dim0; i++) {
        PyObject *o = SWIG_NewPointerObj($1[i], SWIGTYPE_p_Foo, 0);
        PyList_SetItem($result, i, o);
  }
}

刚刚分享了这篇文章,因为我花了很长时间才发现,这篇文章起到了帮助作用。只需要找出如何分配我的非简单类型的SWIG版本——发现它隐藏在这里:

http://www.swig.org/Doc2.0/Python.html#Python_nn64