0
Help us understand the problem. What are the problem?

posted at

pythonでCの関数だけではなく、構造体も参照する方法

pythonから、C言語(シェアードライブラリ)の関数を呼び出す例はありますが、同じようにデータを取り出すやり方です。
C言語のdata構造体をアドレスで参照している場合、pythonでは、下記の様にする必要がありました。

C言語側のdata構造体を指すdata_table_ptrからpython側でdataインスタンスを生成します。

C言語
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);
  :
python
# 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のどちらからでも、データも関数も使用できるようになりました。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?