構造体/共用体

PyFIE では FIE(C 言語) で用意されている構造体及び共用体に対応する PyFIE データ型が用意されています。 これを PyFIE 構造体及び PyFIE 共用体と呼ぶことにします。

PyFIE 構造体及び PyFIE 共用体は FIE(C 言語) で用意されている構造体及び共用体がもつメンバと同名の属性をもち(以下これを単純に "メンバ" と表記します)、 それらのデータを C 言語互換メモリブロックに保持します。

注釈

以下では主に PyFIE 構造体について説明していきますが、 その内容は PyFIE 共用体についても同様となります。


PyFIE 構造体の使用方法

まず PyFIE 構造体はコンストラクタによりインスタンス化されます。 これは C 言語における構造体型変数の宣言に相当します。

C 言語
PNT_T pnt;
Python
pnt = pyfie.PNT_T()

注釈

この例で使用されている PNT_T 構造体は FIE(C 言語) のヘッダーファイルにて下記のように定義されています。

typedef struct {
    INT x;
    INT y;
} PNT_T;

上記のようにコンストラクタの引数に何も指定しなかった場合、 PyFIE 構造体のメンバはすべて 0 で初期化されます。 メンバに初期値を与えてインスタンス化する場合はコンストラクタの引数で初期値を指定します。 このときの引数の順序は、 C 言語の場合と同様に構造体定義におけるメンバの順序となります。

C 言語
PNT_T pnt = { 1, 2 };
Python
pnt = pyfie.PNT_T(1, 2)

コンストラクタの引数では下記のようにキーワード引数も使用することができます。 この場合メンバの名前が引数名となります。

Python
pnt = pyfie.PNT_T(x=1, y=2)

メンバに構造体を含む PyFIE 構造体の初期値設定は下記のように行うことができます。

C 言語
BOX_T box = { {1, 2}, {3, 4} };
Python
box = pyfie.BOX_T((1, 2), (3, 4))

# または下記も同じ.
box = pyfie.BOX_T(st=(1, 2), ed=(3, 4))

注釈

この例で使用されている BOX_T 構造体は FIE(C 言語) のヘッダーファイルにて下記のように定義されています。

typedef struct {
    PNT_T st;
    PNT_T ed;
} BOX_T;

インスタンス化された PyFIE 構造体のメンバには属性を介してアクセスすることができます。

C 言語
PNT_T pnt;
BOX_T box;

pnt.x = 1;
pnt.y = 2;

box.st = pnt;
box.ed.x = 3;
box.ed.y = 4;
Python
pnt = pyfie.PNT_T()
box = pyfie.BOX_T()

pnt.x = 1
pnt.y = 2

box.st = pnt
box.ed.x = 3
box.ed.y = 4

注釈

PyFIE 構造体の各メンバに対する値の設定では、 そのメンバの PyFIE データ型へ変換可能なオブジェクトを使用することができます。

詳しくは各 PyFIE データ型に対する "オブジェクト変換" の説明を参照ください。


ここで PyFIE 構造体インスタンスのメンバを変数に直接代入した場合、 その変数は PyFIE 構造体インスタンスのメンバそのものを参照していることに注意してください。

下記 C 言語と Python のサンプルコードは異なる挙動を示します。

C 言語
PNT_T pnt = { 1, 2 };
INT i;

i = pnt.x;

i = 10;
// i の値に 10 を設定しても
// 当然 pnt.x の値は 2 のままである.
Python
pnt = pyfie.PNT_T(1, 2)

i = pnt.x
# ここで i と pnt.x は同じ実態を参照することになる.

i.value = 10
# i の値に 10 を設定することにより
# 同じ実態である pnt.x の値も 10 となることに注意.

注釈

この挙動は C 言語と Python の言語仕様の違いによるものです。 詳しくは PyFIE データ型を変数に代入する際の C 言語との挙動の違い を参照して下さい。


上記 C 言語サンプルコードと同様のことを PyFIE にて行う場合は、下記のようになります。

C 言語
PNT_T pnt = { 1, 2 };
INT i;

i = pnt.x;

i = 10;
Python
pnt = pyfie.PNT_T(1, 2)
i = pyfie.INT()

i.value = pnt.x
# i の値に pnt.x の値を代入.

i.value = 10
# i の値に 10 を設定しても
# 当然 pnt.x の値は 2 のままである.

PyFIE 構造体の一括代入 (属性 value)

PyFIE 構造体はインスタンス属性 value をもっています。

属性 value には同じ型の PyFIE 構造体インスタンスを代入することができます。 この場合インスタンス間で全てのメンバに対する値のコピーが行われます。

C 言語
PNT_T pnt1 = { 1, 2 };
PNT_T pnt2;

pnt2 = pnt1;

pnt2.x = 10;
Python
pnt1 = pyfie.PNT_T(1, 2)
pnt2 = pyfie.PNT_T()

pnt2.value = pnt1
# pnt2 の全てのメンバの値に pnt1 のメンバの値を代入.

pnt2.x = 10
# pnt2 のメンバを変更しても
# 異なるインスタンスである pnt1 には反映されない.

注釈

属性 value による構造体一括代入では、 構造体インスタンスの他に、 その構造体へ変換可能なオブジェクトも使用することができます。

詳しくは PyFIE 構造体のオブジェクト変換 を参照してください。

また PyFIE 構造体インスタンスの属性 value を参照した場合、 同じメンバ値をもつ新たな PyFIE 構造体インスタンスが得られます。

C 言語
PNT_T pnt1 = { 1, 2 };
PNT_T pnt2 = pnt1;

pnt2.x = 10;
Python
pnt1 = pyfie.PNT_T(1, 2)
pnt2 = pnt1.value
# pnt2 は新たに生成されたインスタンスであり
# そのメンバ値は pnt1 と同じである.

pnt2.x = 10
# pnt2 のメンバを変更しても
# 異なるインスタンスである pnt1 には反映されない.

PyFIE 構造体のポインタ

PyFIE 構造体インスタンスのポインタは属性 ref により取得できます。

C 言語
PNT_T pnt;

&pnt;
Python
pnt = pyfie.PNT_T()

pnt.ref

ポインタについての詳細は ポインタ の章を参照してください。


PyFIE 構造体の演算

PyFIE 構造体の内、一定の条件を満たすものは下記の演算子をサポートします。

二項演算子

+ - * / // % ** << >> & | ^

単項演算子

+ -

代入演算子

+= -= *= /= //= %= **= <<= >>= &= |= ^=

比較演算子

== !=

これらの演算子を使用できる条件は下記です。

  • PyFIE 共用体ではない

  • すべてのメンバの型は以下のいずれか

    • PyFIE 算術型

    • 本節で述べる演算をサポートする PyFIE 構造体

各演算子は同じ型の PyFIE 構造体同士の演算、または Python 組み込みの数値型や PyFIE 算術型との演算に使用することができます。 演算結果は演算に使用した PyFIE 構造体の型となります。

Python
pnt1 = pyfie.PNT_T(1, 2)
pnt2 = pyfie.PNT_T(3, 4)

pnt3 = pnt1 + pnt2  # PyFIE 構造体同士の演算. pnt3 は値 (4, 6) をもつ PNT_T 型となる.
pnt4 = pnt1 + 1     # Python 組み込みの数値型との演算. pnt4 は値 (2, 3) をもつ PNT_T 型となる.

PyFIE 構造体のオブジェクト変換

PyFIE 構造体は特定の状況において、 下記オブジェクトからの変換が可能となります。

  • Python 組み込みのリスト型 ( list

  • Python 組み込みのタプル型 ( tuple

  • numpy.ndarray [1]

  • Python 組み込みのマッピング型 ( dict

リスト型/タプル型から PyFIE 構造体への変換を行う場合は、 (PyFIE 構造体コンストラクタの引数で指定するように) 構造体定義におけるメンバの順序にて要素の値を指定します。

numpy.ndarray から PyFIE 構造体への変換を行う場合は、 numpy.ndarray.tolist により numpy.ndarray をリスト型に変換した後、リスト型と同様に変換します。

マッピング型から PyFIE 構造体への変換を行う場合は、 (PyFIE 構造体コンストラクタのキーワード引数で指定するように) 構造体のメンバ名をキーとして要素の値を指定します。


これらの変換は、 下記状況において行うことができます。

  • PyFIE 構造体の属性 value に対する代入時

  • PyFIE 構造体ポインタの属性 deref に対する代入時

  • PyFIE 構造体配列の各要素に対する代入時

  • PyFIE 構造体の構造体メンバに対する代入時

  • PyFIE 関数の構造体型引数に対する指定時

以下に例を示します。

C 言語
PNT_T pnt;

pnt.x = 1;
pnt.y = 2;
Python
pnt = pyfie.PNT_T()

# 構造体の属性 value に対して
# タプル型で値を設定する例.
pnt.value = 1, 2
C 言語
PNT_T pnt;
PNT_T * p = &pnt;

p->x = 1;
p->y = 2;
Python
pnt = pyfie.PNT_T()
p = pnt.ref   # 構造体 pnt のポインタを取得

# 構造体ポインタの属性 deref に対して
# タプル型で値を設定する例.
p.deref = 1, 2
C 言語
PNT_T pnts[3];

pnts[0].x = 1;
pnts[0].y = 1;
pnts[1].x = 2;
pnts[2].y = 3;
pnts[3].x = 4;
pnts[4].y = 5;
Python
pnts = pyfie.PNT_T.ARRAY(3)

# 構造体配列の各要素に対して
# タプル型で値を設定する例.
pnts[0] = 1, 2
pnts[1] = 3, 4
pnts[2] = 5, 6
C 言語
BOX_T box;

box.st.x = 1;
box.st.y = 2;
box.ed.x = 3;
box.ed.y = 4;
Python
box = pyfie.BOX_T()

# 構造体の構造体メンバに対して
# タプル型で値を設定する例.
box.st = 1, 2
box.ed = 3, 4