pythonから、C言語(シェアードライブラリ)の関数を呼び出す例はありますが、同じようにデータを取り出すやり方です。
C言語のdata構造体をアドレスで参照している場合、pythonでは、下記の様にする必要がありました。
C言語側のdata構造体を指すdata_table_ptrからpython側でdataインスタンスを生成します。
struct data_table {
int attr;
char *data;
};
const struct data_table data = {
.attr = 100,
.data = "文字列",
};
const struct data_table *data_table_ptr = &data; ・・・C①
:
void functionA(const struct data_table *ptr) ・・・C③
{
attr = ptr->attr; ・・・C②
:
}
:
functionA(data_table_ptr);
:
# dllの読み込み処理は省略
from ctypes import *
class data_table(Structure):
_fields_ = [("attr", c_int),
("sata", c_char_p]
:
data = cast(dll.data_table_ptr,POINTER(POINTER(data_table))).contents.contents ・・・python①
:
attr = data.attr ・・・python②
:
:
dll.functionA.restype = None
dll.functionA.argtypes = [POINTER(data_table)] ・・・python③
def functionA(data):
dll.functionA(data)
:
functionA(data)
C①:c言語側のdata_table_ptrは、data構造体のアドレス(ポインタ)を入れるエリアであり、
そのエリアが指す先のアドレス(ポインタ)にdata構造体の実態があります。
data構造体を直接参照するのであれば、
data = cast(dll.data,POINTER(data_table)).contents
です。
data_table_ptr経由では、dataをもう一度ポインタ参照していることになります。
2度ポインター参照しているので、python側では、これをそのままコーディングします。
python①:python側では、data_table_ptrをPOINTER(POINTER(data_table))にキャストした後に、
.contents.contentsでdataインスタンスを取り出すことが出来ます。
python②:dataインスタンスが取り出せたので、python側では、data.attrでデータが参照できます。
python③:c言語側の関数(functionA)を呼び出す場合、アドレス(ポインタ)に変換する為、
functionA.argtypes = [POINTER(data_table)]
と指定することにより、dataのアドレスが、C言語側に渡ります。
C③:呼び出されたfunctionA関数ではポインタ参照でデータを参照できます。
これで、C言語、pythonのどちらからでも、データも関数も使用できるようになりました。