3

我在 c 中有一个全局变量数组,我想将其拉入 python。而且我在使用varouttypemap 时遇到了困难:

/* 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;
}

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

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

$ 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
4

2 回答 2

2

你的类型图几乎就在那里varout。你需要做两个小改动:

  1. 您需要将大小添加ANYint 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};
    

    足以确保它与类型映射匹配varout

通过这两项更改,生成的代码可以按您希望的方式工作:

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;
}

是这些更改在我的机器上生成的。

于 2012-07-27T21:01:35.467 回答
0

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

非简单类型:

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

于 2015-12-20T16:12:43.710 回答