总结与数组成员的C结构在Python中访问:痛饮?用Cython? ctypes的? [英] Wrap C struct with array member for access in python: SWIG? cython? ctypes?

查看:205
本文介绍了总结与数组成员的C结构在Python中访问:痛饮?用Cython? ctypes的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要访问返回包含双阵列结构体从巨蟒(其中这些数组的长度是由结构的其他成员INT给出)的C函数。该声明是

I want to access a C function that returns a struct containing double arrays (where the lengths of these arrays is given by other int members of the struct) from python. The declaration is

typedef struct {
  int dim;
  int vertices;
  int quadrature_degree;
  int polynomial_degree;
  int ngi;
  int quadrature_familiy;
  double *weight; /* 1D: ngi */
  double *l;      /* 2D: ngi * dim */
  double *n;      /* 2D: ngi * vertices */
  double *dn;     /* 3D: ngi * vertices * dim */
} element;

extern void get_element(int dim, int vertices, int quad_degree, int poly_degree, element* e);

重要的一点是我希望能够访问所有的双* 成员正确的形状的numpy的阵列(即 DN 应该是一个可访问的三维阵列)。

The important point is I want to be able to access all the double* members as NumPy arrays of the correct shape (i.e. dn should be a accessible as 3D array).

简单地痛饮,包装这给了我这个结构就好了,但所有的双* 成员<类型痛饮对象双* 在0x348c8a0> 这使得它们毫无用处。我玩与周围的numpy的SWIG接口文件,但无法得到任何的typemaps像(DATA_TYPE * INPLACE_ARRAY1,诠释DIM1)的工作(我认为这是不可能得到它们匹配在这种情况下,但我很乐意被证明是错误的)。

Simply SWIG-wrapping this gives me the struct just fine, but all the double* members are <Swig Object of type 'double *' at 0x348c8a0> which makes them useless. I played around with the NumPy SWIG interface file but couldn't get any of the typemaps like ( DATA_TYPE* INPLACE_ARRAY1, int DIM1 ) to work (I think it's not possible to get them to match in this case but I'd be happy to be proven wrong).

我的猜测是我不得不在numpy的数组作为 PyArrayObject 这些成员和痛饮的手code初始化致以结构,使它们在Python访问?这看起来像一个大量的工作。任何人都可以看到使用痛饮一个更好的方法吗?这将有可能改变结构或方法返回,如果,使得事情变得更加容易。

My guess is I'd have to hand code initialization of the NumPy arrays as PyArrayObject for these members and SWIG extend my struct to make them accessible in Python? That looks like a lot of work. Can anyone see a nicer way using SWIG? It would be possible to change the struct or the method returning it if that made things easier.

另外我看了一下用Cython和ctypes的。将这些更适合于我想要达到什么目的?我没有使用过这样用Cython无法判断它的包装能力。对于ctypes的我可以大致想象如何做到这一点,但它的手就是写我所希望一个合理的自动包装可以为我做的。

Alternatively I had a look at cython and ctypes. Would these be better suited for what I'm trying to achieve? I haven't used cython so can't judge it's wrapping capabilities. For ctypes I can roughly imagine how to do it, but it means writing by hand what I had hoped a reasonably automated wrapper could do for me.

任何建议感激地接受!

推荐答案

使用痛饮,需要对整个结构类型映射一个。对于只有指针构件Tyepmaps是不够的,因为它们不具有知道大小与初始化numpy的阵列的上下文。我设法得到我想要的东西有以下typemaps(这基本上是复制和放大器;从numpy.i粘贴和适应我的需要,可能不会很强劲):

Using SWIG requires a typemap for the entire struct. Tyepmaps for only the pointer members are not enough, since they don't have the context to know what size to initialize the NumPy arrays with. I managed to get what I wanted with the following typemaps (which was basically copy & paste from numpy.i and adapt to my needs, probably not very robust):

%typemap (in,numinputs=0) element * (element temp) {
  $1 = &temp;
}

%typemap (argout) element * {
  /* weight */
  {
    npy_intp dims[1] = { $1->ngi };
    PyObject * array = PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, (void*)($1->weight));
    if (!array) SWIG_fail;
    $result = SWIG_Python_AppendOutput($result,array);
  }
  /* l */
  {
    npy_intp dims[2] = { $1->ngi, $1->dim };
    PyObject * array = PyArray_SimpleNewFromData(2, dims, NPY_DOUBLE, (void*)($1->l));
    if (!array) SWIG_fail;
    $result = SWIG_Python_AppendOutput($result,array);
  }
  /* n */
  {
    npy_intp dims[2] = { $1->ngi, $1->vertices };
    PyObject * array = PyArray_SimpleNewFromData(2, dims, NPY_DOUBLE, (void*)($1->n));
    if (!array) SWIG_fail;
    $result = SWIG_Python_AppendOutput($result,array);
  }
  /* dn */
  {
    npy_intp dims[3] = { $1->ngi, $1->vertices, $1->dim };
    PyObject * array = PyArray_SimpleNewFromData(3, dims, NPY_DOUBLE, (void*)($1->dn));
    if (!array) SWIG_fail;
    $result = SWIG_Python_AppendOutput($result,array);
  }
}

该工程从C函数不同,它返回numpy的阵列的元组与我想要的数据,这比从提取物更方便元素后来反对。第一类型映射还省去了在键入元素的目的在于传递。因此,我可以隐藏元素从Python用户完全结构体。

This works different from the C function in that it returns a tuple of NumPy arrays with the data I want, which is more convenient than having to extract it from the element object later. The first typemap furthermore eliminates the need to pass in an object of type element. Hence I can hide the element struct entirely from the python user.

Python接口终于看起来像这样:

The python interface finally looks like this:

weight, l, n, dn = get_element(dim, vertices, quadrature_degree, polynomial_degree)

这篇关于总结与数组成员的C结构在Python中访问:痛饮?用Cython? ctypes的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆