LoginSignup
9
10

More than 5 years have passed since last update.

Python C/C++ 拡張: データの一部を np.array として Python に渡す (stride を設定)

Last updated at Posted at 2016-06-16

C/C++ のデータを np.array として Python から見る。

typedef struct Particle {
  float x[3], v[3];
} Particle;

const int np=10;
Particle* const p= calloc(sizeof(Particle), np);

for(int i=0; i<np; ++i) {
  p[i].x[0]= (float) i + 1;
}

これを np.array として Python に渡したい場合は PyArray_SimpleNewFromData 関数を使えば良い。1

しかし、ここでは、データの一部、x[3] だけを np.array としてPythonに渡す方法を紹介する。データ構造が複数の型を含んでいて、全てをひとつの np.array にできない場合などもあるでしょう。

このようにデータがメモリに連続して存在しないけれど、一定間隔で並んでいる場合は strides を設定すればよい。2

PyObject* PyArray_New(PyTypeObject* subtype, int nd, npy_intp* dims, 
                       int type_num, npy_intp* strides, void* data, 
                       int itemsize, int flags, PyObject* obj);

strides[] とは a を np.array とするとき、strides[0]a[i,j]a[i+1,j] のバイト差、strides[1]a[i,j]a[i,j+1] のバイト差。

static PyObject* py_as_nparray(PyObject *self, PyObject *args)
{
  const int nd=2;
  const int ncol= 3;
  npy_intp dims[]= {np, ncol};
  npy_intp strides[]= {sizeof(Particle), sizeof(float)};

  return PyArray_New(&PyArray_Type, nd, dims, NPY_FLOAT, strides, p->x, 0, 0, 0);
}

Python から使った結果

import numpy as np
import cext08

a = cext08.as_nparray()

[[  1.   0.   0.]
 [  2.   0.   0.]
 [  3.   0.   0.]
 [  4.   0.   0.]
 ...

* 実際に使うときは Particle* p のメモリは Python で使っている間は解放されず、解放する場合は C のほうでなんとかするとします。

コード全体は github にあります

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10