ctypes とは:
ctypes
C言語と対話するためのPythonの標準ライブラリです。ダイナミック リンク ライブラリ (DLL) または共有オブジェクト (SO) で C 関数を簡単に呼び出し、C データ型の変換を処理できる一連のツールと関数を提供します。
簡単に言うと、ctypes は c と Python 間の型変換を行います。型変換が完了したので、次に ctypes を使用して C/C++ で一般的に使用される型を変換する方法を見てみましょう。
ダイナミック リンク ライブラリとは次のとおりです。
ダイナミック リンク ライブラリは、コンパイルされたデータ関数ライブラリであり、プログラムの実行時に直接使用できます。スタティック リンク ライブラリとは異なり、ダイナミック リンク ライブラリは、コンパイル時ではなく、プログラムの実行時にロードおよびリンクされます。ダイナミック リンク ライブラリを最初にロードする必要があります。この目的のために、ctypes は 3 つのオブジェクトを提供します: cdll、windll (Windows のみ) 、oledll (Windows のみ) を使用すると、これらのオブジェクトのプロパティにアクセスするのと同じように dll をロードできます。3 つの違いは次のとおりです。
(1) cdll: cdll オブジェクトは、標準の cdecl 呼び出し規約を使用して関数ライブラリをロードします。
(2) Windll: Windll オブジェクトは、stdcall 呼び出し規則を使用して関数ライブラリをロードします。
(3) oledll: oledll オブジェクトは、stdcall 呼び出し規則を使用して関数ライブラリをロードします。
使用手順:
(1) ダイナミック リンク ライブラリをロードします。
or (Windows プラットフォーム)ctypes
関数 を使用して、 ダイナミック リンク ライブラリまたは共有オブジェクトをロードします。ライブラリのパスまたは名前を指定するだけで、 オペレーティング システムに基づいて正しいロード関数が自動的に選択されます。cdll
windll
ctypes
例は次のとおりです。
# 示例 1: 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
# 示例 2: 加载共享对象(在 Windows 上)
my_lib = ctypes.windll.LoadLibrary('my_lib.dll')
(2) DLL/共有ライブラリ内の関数を取得する
my_function = my_lib.my_function # my_function 是动态库中已导出的函数,不导出则不可调用,像访问一个类实例属性一样来载入my_function.argtypes = [ctypes.c_int, ctypes.c_float] my_function.restype = ctypes.c_double # 指定函数的返回类型和参数类型。
(3) 呼び出し元の c 関数に渡せるように型変換を実行します。
(1) C言語の基本的なデータ型
この部分の使用方法は比較的簡単です。ctypes の組み込みメソッドを直接使用してオブジェクトを作成できます。ctypes が提供するメソッドと C 言語に対応するデータ型は次のとおりです。
ctypes タイプ |
Cタイプ |
Python の種類 |
---|---|---|
_ブール |
ブール (1) |
|
文字 |
単一文字のバイトオブジェクト |
|
|
単一の文字列 |
|
文字 |
整数 |
|
符号なし文字 |
整数 |
|
短い |
整数 |
|
符号なしショート |
整数 |
|
整数 |
整数 |
|
符号なし整数 |
整数 |
|
長さ |
整数 |
|
符号なしロング |
整数 |
|
__int64 または Long Long |
整数 |
|
unsigned __int64 または unsigned long long |
整数 |
|
|
整数 |
|
|
整数 |
|
浮く |
浮く |
|
ダブル |
浮く |
|
ロングダブル |
浮く |
|
char* (NUL で終了) |
バイトオブジェクトまたは |
|
wchar_t* (NUL で終了) |
文字列または |
|
空所* |
int または |
いくつかの小さな使用例:
import ctypes
# 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
# 定义函数原型
my_function = my_lib.my_function
my_function.argtypes = [ctypes.c_int]
# 转换整型数据类
my_int = 10
my_function(ctypes.c_int(my_int))
#转换浮点型数据类型:
my_float = 3.14
my_function(ctypes.c_float(my_float))
#转换字符串类型:
my_string = "Hello"
my_function(ctypes.c_char_p(my_string.encode('utf-8')))#转换数组类型:char_array = c_char * 3
(2) C言語の高度なデータ型
構造体、ネストされた構造体、構造体配列、構造体ポインターなどの C 言語の高度なデータ型の場合、ctypes
変換用のツールとメソッドがいくつか提供されています。C コードに構造体型があると仮定します。 MyStruct,
いくつかの例を次に示します。
import ctypes
# 定义 C 结构体类型
class MyStruct(ctypes.Structure):
_fields_ = [("field1", ctypes.c_int),
("field2", ctypes.c_float)]
# 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
# 定义函数原型
my_function = my_lib.my_function
my_function.argtypes = [MyStruct]
# 创建结构体实例并传递给 C 函数
my_struct = MyStruct()
my_struct.field1 = 10
my_struct.field2 = 3.14
my_function(my_struct)
#转换嵌套结构体
class InnerStruct(ctypes.Structure):
_fields_ = [("inner_field", ctypes.c_int)] # 定义 C 内部引用结构体class OuterStruct(ctypes.Structure):
_fields_ = [("outer_field", ctypes.POINTER(InnerStruct))] # 创建结构体实例,并传递给 C 函数
inner = InnerStruct()
inner.inner_field = 10
outer = OuterStruct()
outer.outer_field = ctypes.pointer(inner)
my_function(ctypes.cast(ctypes.pointer(outer), ctypes.POINTER(OuterStruct)))array_size = 5
my_array = (MyStruct * array_size)()
for i in range(array_size):
my_array[i].field1 = i
my_array[i].field2 = float(i)
my_function(my_array, array_size)#转换结构体指针和结构体指针数组:#对于结构体指针和结构体指针数组,可以使用 ctypes.POINTER 类型和 ctypes.cast 函数进行转换。# 定义函数原型
my_function = my_lib.my_function
my_function.argtypes = [ctypes.POINTER(MyStruct)]
# 创建结构体实例,并传递给 C 函数
my_struct = MyStruct()
my_struct.field1 = 10
my_struct.field2 = 3.14
# 传递结构体指针给 C 函数
my_function(ctypes.pointer(my_struct))
# 创建结构体指针数组,并传递给 C 函数
array_size = 5
my_array = (ctypes.POINTER(MyStruct) * array_size)()
for i in range(array_size):
my_array[i] = ctypes.pointer(MyStruct())
my_function(ctypes.cast(my_array, ctypes.POINTER(ctypes.POINTER(MyStruct))))
(3) C言語のコールバック関数の変換
register_callback
関数ポインターをパラメーターとして受け取り、適切なタイミングでその関数を呼び出す関数が C コードにあるとします 。ctypes
を使用してコールバック関数を定義し、それを に渡すこと ができます register_callback
。
まず、コールバック関数の型を定義し、それを関数ポインター型に変換する必要があります。を呼び出すときは register_callback
、変換された関数ポインタを引数として渡します。
import ctypes
# 定义回调函数类型
CallbackFunc = ctypes.CFUNCTYPE(None, ctypes.c_int)
# 定义回调函数
def my_callback(value):
print("Callback called with value:", value)
# 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
# 定义函数原型
register_callback = my_lib.register_callback
register_callback.argtypes = [CallbackFunc]
# 将 Python 回调函数转换为函数指针
callback_func = CallbackFunc(my_callback)
# 注册回调函数
register_callback(callback_func)
まず、 ctypes.CFUNCTYPE
定義されたコールバック関数 type を使用しますCallbackFunc
。最初のパラメータはコールバック関数の戻り値の型で、ここでは です None
。これは戻り値がないことを意味します。2 番目のパラメータはコールバック関数のパラメータの型で、ここでは です ctypes.c_int
。
my_callback
次に、整数の引数を受け入れ、関数内でその引数の値を出力するコールバック関数を Python で定義しました 。
次に、 を 使用してCallbackFunc
Python コールバック関数を関数ポインタ型に変換します callback_func
。
register_callback
最後に、ダイナミック リンク ライブラリをロードして関数を呼び出し 、変換された関数ポインタをパラメータとして C 関数に渡します。
情報の入手方法
【メッセージ777】
ソースコードやその他のチュートリアル資料を入手したいお友達は、「いいね!」 + コメント + 収集を3 回続けてお願いします。
3ラウンド連続で終わったら、コメント欄に個別メッセージを送ります〜