ctypes の使用に関する簡単な説明

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 関数   を使用して、  ダイナミック リンク ライブラリまたは共有オブジェクトをロードします。ライブラリのパスまたは名前を指定するだけで、 オペレーティング システムに基づいて正しいロード関数が自動的に選択されます。cdllwindllctypes

例は次のとおりです。


# 示例 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 の種類

c_bool

_ブール

ブール (1)

c_char

文字

単一文字のバイトオブジェクト

c_wchar

wchar_t

単一の文字列

c_byte

文字

整数

c_ubyte

符号なし文字

整数

c_short

短い

整数

c_ushort

符号なしショート

整数

c_int

整数

整数

c_uint

符号なし整数

整数

c_long

長さ

整数

c_olong

符号なしロング

整数

c_longlong

__int64 または Long Long

整数

c_ulonglong

unsigned __int64 または unsigned long long

整数

c_size_t

size_t

整数

c_ssize_t

ssize_t または Py_ssize_t

整数

c_float

浮く

浮く

c_double

ダブル

浮く

c_longdouble

ロングダブル

浮く

c_char_p

char* (NUL で終了)

バイトオブジェクトまたは None

c_wchar_p

wchar_t* (NUL で終了)

文字列または None

c_void_p

空所*

int または None

いくつかの小さな使用例:


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ラウンド連続で終わったら、コメント欄に個別メッセージを送ります〜

おすすめ

転載: blog.csdn.net/GDYY3721/article/details/132210265