Python調(diào)用C語言動態(tài)庫的方法小結(jié)
ctypes
是 Python 的外部函數(shù)庫。它提供了與 C 兼容的數(shù)據(jù)類型,并允許調(diào)用 DLL 或共享庫中的函數(shù)??墒褂迷撃K以純 Python 形式對這些庫進(jìn)行封裝。
基本數(shù)據(jù)類型對應(yīng)關(guān)系
[ctypes
] 定義了一些和C兼容的基本數(shù)據(jù)類型:
ctypes 類型 | C 類型 | Python 類型 |
---|---|---|
[c_bool] | _Bool | bool (1) |
[c_char] | char | 單字符字節(jié)串對象 |
[c_wchar] | wchar_t | 單字符字符串 |
[c_byte] | char | int |
[c_ubyte] | unsigned char | int |
[c_short] | short | int |
[c_ushort] | unsigned short | int |
[c_int] | int | int |
[c_uint] | unsigned int | int |
[c_long] | long | int |
[c_ulong] | unsigned long | int |
[c_longlong] | __int64 或 long long | int |
[c_ulonglong] | unsigned __int64 或 unsigned long long | int |
[c_size_t] | size_t | int |
[c_ssize_t] | ssize_t 或 Py_ssize_t | int |
[c_float] | float | float |
[c_double] | double | float |
[c_longdouble] | long double | float |
[c_char_p] | char * (NUL terminated) | 字節(jié)串對象或 None |
[c_wchar_p] | wchar_t * (NUL terminated) | 字符串或 None |
[c_void_p] | void * | int 或 None |
環(huán)境
開發(fā)工具:Clion
C語言版本:C11
Python版本:Python3.8
創(chuàng)建項目
CMakeLists.txt
# 指定 CMake 的最低版本要求 cmake_minimum_required(VERSION 3.30) # 定義項目名稱和支持的語言類型 project(CLibSharedDemo C) # 設(shè)置 C 標(biāo)準(zhǔn)版本為 C11 set(CMAKE_C_STANDARD 11) # 添加共享庫目標(biāo),將 library.c 編譯為動態(tài)庫 (Windows 下為 .dll,Linux 下為 .so,macOS 下為 .dylib) add_library(CLibSharedDemo SHARED library.c)
library.h
#ifndef CLIBSHAREDDEMO_LIBRARY_H #define CLIBSHAREDDEMO_LIBRARY_H #include <wchar.h> void plus(int a, int *result); void *process_void_pointer(void *ptr); _Bool is_even(int num); int add_int(int a, int b); short add_short(short a, short b); long add_long(long a, long b); long long add_longlong(long long a, long long b); unsigned int add_unsigned_int(unsigned int a, unsigned int b); unsigned short add_unsigned_short(unsigned short a, unsigned short b); unsigned long add_unsigned_long(unsigned long a, unsigned long b); unsigned long long add_unsigned_longlong(unsigned long long a, unsigned long long b); float add_float(float a, float b); double add_double(double a, double b); char to_upper(char c); wchar_t to_upper_wchar(wchar_t wc); char *copy_string(const char *src, char *dest); wchar_t *copy_wstring(const wchar_t *src, wchar_t *dest); size_t add_size_t(size_t a, size_t b); ssize_t add_ssize_t(ssize_t a, ssize_t b); void fill_array(int *arr, int size); typedef struct { char name[50]; int age; } Person; Person update_person_by_value(Person p); void update_person_by_pointer(Person *p); #endif //CLIBSHAREDDEMO_LIBRARY_H
library.c
#include "library.h" #include <stdio.h> #include <string.h> #include <wchar.h> // void void plus(const int a, int *result) { *result = a + 1; } // void * void *process_void_pointer(void *ptr) { return ptr; } // _Bool _Bool is_even(const int num) { return num % 2 == 0; } // int int add_int(const int a, const int b) { return a + b; } // short short add_short(const short a, const short b) { return a + b; } // long long add_long(const long a, const long b) { return a + b; } // long long long long add_longlong(const long long a, const long long b) { return a + b; } // unsigned int unsigned int add_unsigned_int(const unsigned int a, const unsigned int b) { return a + b; } // unsigned short unsigned short add_unsigned_short(const unsigned short a, const unsigned short b) { return a + b; } // unsigned long unsigned long add_unsigned_long(const unsigned long a, const unsigned long b) { return a + b; } // unsigned long long unsigned long long add_unsigned_longlong(const unsigned long long a, const unsigned long long b) { return a + b; } // float float add_float(const float a, const float b) { return a + b; } // double double add_double(const double a, const double b) { return a + b; } // char char to_upper(const char c) { if (c >= 'a' && c <= 'z') { return c - ('a' - 'A'); } return c; } // wchar_t wchar_t to_upper_wchar(const wchar_t wc) { if (wc >= L'a' && wc <= L'z') { return wc - (L'a' - L'A'); } return wc; } // char * char *copy_string(const char *src, char *dest) { strcpy(dest, src); return dest; } // wchar_t * wchar_t *copy_wstring(const wchar_t *src, wchar_t *dest) { wcscpy(dest, src); return dest; } // size_t size_t add_size_t(const size_t a, const size_t b) { return a + b; } // ssize_t ssize_t add_ssize_t(const ssize_t a, const ssize_t b) { return a + b; } // arr void fill_array(int *arr, int size) { for (int i = 0; i < size; i++) { arr[i] = arr[i] * i; } } // struct Person update_person_by_value(Person p) { p.age += 1; // 修改 age return p; } void update_person_by_pointer(Person *p) { if (p != NULL) { p->age += 1; // 修改 age } }
編譯
選擇菜單【Build】 - 【Build Project】,編譯生成動態(tài)庫在 cmake-build-debug
目錄下。
使用
# main.py import ctypes import platform """ 官方參考文檔:https://docs.python.org/zh-cn/3.8/library/ctypes.html """ # 獲取當(dāng)前操作系統(tǒng)的名稱 current_platform = platform.system() # 根據(jù)操作系統(tǒng)設(shè)置庫的路徑 if current_platform == "Windows": lib = ctypes.CDLL("./cmake-build-debug/libCLibSharedDemo.dll") # Windows elif current_platform == "Linux": lib = ctypes.CDLL("./cmake-build-debug/libCLibSharedDemo.so") # Linux elif current_platform == "Darwin": # macOS的名稱是 Darwin lib = ctypes.CDLL("./cmake-build-debug/libCLibSharedDemo.dylib") # macOS else: raise OSError("Unsupported platform") """ 空值 """ # void lib.plus.argtypes = (ctypes.c_int, ctypes.POINTER(ctypes.c_int)) lib.plus.restype = None result = ctypes.c_int() # 創(chuàng)建一個 ctypes 整型變量作為結(jié)果 lib.plus(5, ctypes.byref(result)) # 使用 ctypes.byref 傳遞指針 print("void:", result.value) # 輸出: Result: 6 # void * lib.process_void_pointer.argtypes = (ctypes.c_void_p,) lib.process_void_pointer.restype = ctypes.c_void_p ptr = ctypes.pointer(ctypes.c_int(42)) print("void *: ", lib.process_void_pointer(ptr)) # 輸出: 2320620323976 """ 布爾 """ # _Bool -> c_bool lib.is_even.argtypes = (ctypes.c_int,) lib.is_even.restype = ctypes.c_bool print("_Bool:", lib.is_even(4)) # 輸出: True """ 整數(shù)/浮點數(shù) """ # int -> c_int lib.add_int.argtypes = (ctypes.c_int, ctypes.c_int) lib.add_int.restype = ctypes.c_int print("int:", lib.add_int(10, 20)) # 輸出: 30 # short -> c_short lib.add_short.argtypes = (ctypes.c_short, ctypes.c_short) lib.add_short.restype = ctypes.c_short print("short:", lib.add_short(3200, 10)) # 輸出: 3210 # long -> c_long lib.add_long.argtypes = (ctypes.c_long, ctypes.c_long) lib.add_long.restype = ctypes.c_long print("long:", lib.add_long(10000, 2000)) # 輸出: 12000 # long long -> c_longlong lib.add_longlong.argtypes = (ctypes.c_longlong, ctypes.c_longlong) lib.add_longlong.restype = ctypes.c_longlong print("long long:", lib.add_longlong(100000000000, 200000000000)) # 輸出: 300000000000 # unsigned int -> c_uint lib.add_unsigned_int.argtypes = (ctypes.c_uint, ctypes.c_uint) lib.add_unsigned_int.restype = ctypes.c_uint print("unsigned int:", lib.add_unsigned_int(10, 20)) # 輸出: 30 # unsigned short -> c_ushort lib.add_unsigned_short.argtypes = (ctypes.c_ushort, ctypes.c_ushort) lib.add_unsigned_short.restype = ctypes.c_ushort print("unsigned short:", lib.add_unsigned_short(3200, 10)) # 輸出: 3210 # unsigned long -> c_ulong lib.add_unsigned_long.argtypes = (ctypes.c_ulong, ctypes.c_ulong) lib.add_unsigned_long.restype = ctypes.c_ulong print("unsigned long:", lib.add_unsigned_long(10000, 2000)) # 輸出: 12000 # unsigned long long -> c_ulonglong lib.add_unsigned_longlong.argtypes = (ctypes.c_ulonglong, ctypes.c_ulonglong) lib.add_unsigned_longlong.restype = ctypes.c_ulonglong print("unsigned long long:", lib.add_unsigned_longlong(100000000000, 200000000000)) # 輸出: 300000000000 # float -> c_float lib.add_float.argtypes = (ctypes.c_float, ctypes.c_float) lib.add_float.restype = ctypes.c_float print("float:", lib.add_float(3.5, 2.0)) # 輸出: 5.5 # double -> c_double lib.add_double.argtypes = (ctypes.c_double, ctypes.c_double) lib.add_double.restype = ctypes.c_double print("double:", lib.add_double(1.5, 2.5)) # 輸出: 4.0 """ 字符/字符串 """ # char -> c_char lib.to_upper.argtypes = (ctypes.c_char,) lib.to_upper.restype = ctypes.c_char print("char:", lib.to_upper("a".encode()).decode()) # 輸出: 'A' # wchar_t -> c_wchar lib.to_upper_wchar.argtypes = (ctypes.c_wchar,) lib.to_upper_wchar.restype = ctypes.c_wchar print("wchar_t:", lib.to_upper_wchar("a")) # 輸出: 'A' # char * -> c_char_p lib.copy_string.argtypes = (ctypes.c_char_p, ctypes.c_char_p) lib.copy_string.restype = ctypes.c_char_p src_str = "Hello" dest_str = ctypes.create_string_buffer(100) # 預(yù)留 100 字節(jié)緩沖區(qū) result = lib.copy_string(src_str.encode(), dest_str) print("char *:", result.decode()) # 輸出: 'Hello' # wchar_t * -> c_wchar_p lib.copy_wstring.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p) lib.copy_wstring.restype = ctypes.c_wchar_p src_wstr = "Hello Wide" dest_wstr = ctypes.create_unicode_buffer(100) # 預(yù)留 100 個寬字符緩沖區(qū) result = lib.copy_wstring(src_wstr, dest_wstr) print("wchar_t *:", result) # 輸出: 'Hello Wide' """ 指針 """ # int * -> ctypes.POINTER(ctypes.c_int) lib.plus.argtypes = (ctypes.c_int, ctypes.POINTER(ctypes.c_int)) lib.plus.restype = None result = ctypes.c_int() lib.plus(5, ctypes.byref(result)) # ctypes.byref 直接傳遞原有變量的地址 print("int *:", result.value) # 輸出: Result: 6 result = ctypes.c_int() lib.plus(5, ctypes.pointer(result)) # ctypes.pointer 顯式地創(chuàng)建一個指針對象 print("int *:", result.value) # 輸出: Result: 6 """ 內(nèi)存大小 """ # size_t -> c_size_t lib.add_size_t.argtypes = (ctypes.c_size_t, ctypes.c_size_t) lib.add_size_t.restype = ctypes.c_size_t print("size_t:", lib.add_size_t(10, 20)) # 輸出: 30 # ssize_t -> c_ssize_t lib.add_ssize_t.argtypes = (ctypes.c_ssize_t, ctypes.c_ssize_t) lib.add_ssize_t.restype = ctypes.c_ssize_t print("ssize_t:", lib.add_ssize_t(10, 20)) # 輸出: 30 """ 數(shù)組 """ lib.fill_array.argtypes = (ctypes.POINTER(ctypes.c_int), ctypes.c_int) lib.fill_array.restype = None ls = [1, 3, 5] arr = (ctypes.c_int * len(ls))(*ls) lib.fill_array(arr, len(arr)) print("array:", list(arr)) # array: [0, 3, 10] """ 結(jié)構(gòu)體 """ class Person(ctypes.Structure): _fields_ = [("name", ctypes.c_char * 50), ("age", ctypes.c_int)] # 情況 1:入?yún)⒑头祷刂刀际墙Y(jié)構(gòu)體 lib.update_person_by_value.argtypes = (Person,) lib.update_person_by_value.restype = Person person1 = Person(name="Alice".encode(), age=25) print(f"Before (Value): name={person1.name.decode()}, age={person1.age}") updated_person = lib.update_person_by_value(person1) print(f"After (Value): name={updated_person.name.decode()}, age={updated_person.age}") # 情況 2:入?yún)榻Y(jié)構(gòu)體指針 lib.update_person_by_pointer.argtypes = (ctypes.POINTER(Person),) lib.update_person_by_pointer.restype = None person2 = Person(name="Bob".encode(), age=30) print(f"Before (Pointer): name={person2.name.decode()}, age={person2.age}") lib.update_person_by_pointer(ctypes.byref(person2)) print(f"After (Pointer): name={person2.name.decode()}, age={person2.age}")
到此這篇關(guān)于Python調(diào)用C語言動態(tài)庫的方法小結(jié)的文章就介紹到這了,更多相關(guān)Python調(diào)用C語言動態(tài)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python獲取接口數(shù)據(jù)的實現(xiàn)示例
本文主要介紹了Python獲取接口數(shù)據(jù)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07python中plt.imshow與cv2.imshow顯示顏色問題
這篇文章主要介紹了plt.imshow與cv2.imshow顯示顏色問題,本文給大家介紹的非常詳細(xì),同時給大家提到了cv2.imshow()和plt.imshow()的區(qū)別講解,需要的朋友可以參考下2020-07-07如何實現(xiàn)Python調(diào)用Golang代碼詳解
這篇文章主要介紹了如何實現(xiàn)Python調(diào)用Golang代碼,Python和Golang都是當(dāng)下非常流行的編程語言,在實際開發(fā)中,我們可能會遇到需要將Python和Golang進(jìn)行組合使用的場景,感興趣想要詳細(xì)了解可以參考下文2023-05-05Python標(biāo)準(zhǔn)庫之typing的用法(類型標(biāo)注)
這篇文章主要介紹了Python標(biāo)準(zhǔn)庫之typing的用法(類型標(biāo)注),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Python tkinter的grid布局及Text動態(tài)顯示方法
今天小編就為大家分享一篇Python tkinter的grid布局及Text動態(tài)顯示方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10Python GUI編程之tkinter模塊Toplevel控件實現(xiàn)搭建父子窗口
這篇文章主要介紹了Python使用tkinter模塊Toplevel控件搭建父子窗口的實現(xiàn)方法,Tkinter是Python的標(biāo)準(zhǔn)GUI庫,Python使用Tkinter可以快速的創(chuàng)建GUI應(yīng)用程序,用到相關(guān)控件的同學(xué)可以參考下2023-12-12