はじめに
PythonでC言語風な構造体を使いたくて悶々したときに使える手法。
例えば↓のよう構造体を作りたい場合。
c_struct.h
typedef struct{
float pos[4];
unsigned char class;
float score;
} HOGE;
HOGE fuga[10];
Pythonでの表現方法
Structured Datatypesを使用する
- https://numpy.org/doc/stable/user/basics.rec.html#structured-datatypes
- https://jakevdp.github.io/PythonDataScienceHandbook/02.09-structured-data-numpy.html
c_like_struct.py
import numpy as np
HOGE = np.dtype([("pos", np.float32, (4,)),
("class", np.uint8, (1,)),
("score", np.float32, (1,)),
],
align=True
)
fuga = np.zeros(10, dtype=HOGE)
これでC言語風な構造体が表現できる。
上記でalign=Trueとすることでパディングされる。
使い方確認①(とりあえず出力)
処理
print(HOGE)
print(fuga)
結果
{'names':['pos','class','score'], 'formats':[('<f4', (4,)),('u1', (1,)),('<f4', (1,))], 'offsets':[0,16,20], 'itemsize':24, 'aligned':True}
[([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])]
使い方確認②(dtype, shape)
処理
print("fuga.dtype: ",fuga.dtype)
print("fuga.shape: ",fuga.shape)
print("fuga.['pos'].shape: ",fuga['pos'].shape)
print("fuga.['pos'][0].shape: ",fuga['pos'][0].shape)
print("fuga['pos'][1]: ", fuga['pos'][1])
結果
fuga.dtype: {'names':['pos','class','score'], 'formats':[('<f4', (4,)),('u1', (1,)),('<f4', (1,))], 'offsets':[0,16,20], 'itemsize':24, 'aligned':True}
fuga.shape: (10,)
fuga['pos'].shape: (10, 4)
fuga['pos'][0].shape: (4,)
fuga['pos'][1]: [0. 0. 0. 0.]
使い方確認③(np.recarray)
処理
piyo = fuga.view(np.recarray)
print("piyo: ", piyo)
print("piyo.pos.shape: ", piyo.pos.shape)
print("piyo.pos[0].shape: ", piyo.pos[0].shape)
print("piyo.pos[1]: ",piyo.pos[1])
結果
piyo: [([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])
([0., 0., 0., 0.], [0], [0.]) ([0., 0., 0., 0.], [0], [0.])]
piyo.pos.shape: (10, 4)
piyo.pos[0].shape: (4,)
piyo.pos[1]: [0. 0. 0. 0.]
使い方確認④(代入処理)
処理
fuga['pos'][1] = [-1.0 , 2.3, 0.42, 0.0]
print("fuga['pos'][:3]: ",fuga['pos'][:3])
結果
fuga['pos'][:3]: [[ 0. 0. 0. 0. ]
[-1. 2.3 0.42 0. ]
[ 0. 0. 0. 0. ]]