【Python】python调用dll
·
1. 使用 ctypes(最常用)
基本用法
from ctypes import *
# 加载DLL
mydll = CDLL('mydll.dll') # Windows
# mydll = CDLL('./libmylib.so') # Linux
# 调用函数
result = mydll.add(5, 3)
print(f"5 + 3 = {result}")
mydll.hello()
完整示例
from ctypes import *
import os
# 加载DLL
dll_path = os.path.join(os.path.dirname(__file__), 'mydll.dll')
mydll = CDLL(dll_path)
# 指定参数和返回类型(重要!)
mydll.add.argtypes = [c_int, c_int]
mydll.add.restype = c_int
mydll.hello.argtypes = []
mydll.hello.restype = None
# 调用函数
result = mydll.add(10, 20)
print(f"10 + 20 = {result}")
mydll.hello()
2. 处理不同数据类型
基本数据类型
from ctypes import *
mydll = CDLL('mydll.dll')
# 各种C数据类型
mydll.func_int.argtypes = [c_int]
mydll.func_int.restype = c_int
mydll.func_double.argtypes = [c_double]
mydll.func_double.restype = c_double
mydll.func_bool.argtypes = [c_bool]
mydll.func_bool.restype = c_bool
字符串参数
# C函数:void print_string(char* str)
mydll.print_string.argtypes = [c_char_p]
mydll.print_string.restype = None
# 传递字符串
mydll.print_string(b"Hello from Python!") # 注意使用bytes
mydll.print_string("中文".encode('utf-8')) # 中文需要编码
指针和数组
# C函数:void process_array(int* arr, int size)
mydll.process_array.argtypes = [POINTER(c_int), c_int]
mydll.process_array.restype = None
# 创建数组
arr = (c_int * 5)(1, 2, 3, 4, 5)
mydll.process_array(arr, 5)
# 读取结果
print(list(arr))
3. 结构体处理
C结构体定义
// point.dll
typedef struct {
int x;
int y;
} Point;
__declspec(dllexport) double distance(Point* p1, Point* p2);
Python对应代码
from ctypes import *
# 定义对应的结构体
class Point(Structure):
_fields_ = [
('x', c_int),
('y', c_int)
]
# 加载DLL
point_dll = CDLL('point.dll')
# 设置函数原型
point_dll.distance.argtypes = [POINTER(Point), POINTER(Point)]
point_dll.distance.restype = c_double
# 创建结构体实例
p1 = Point(10, 20)
p2 = Point(30, 40)
# 调用函数
dist = point_dll.distance(byref(p1), byref(p2))
print(f"Distance: {dist}")
4. 回调函数
C回调函数
// callback.dll
typedef void (*Callback)(int progress);
__declspec(dllexport) void long_operation(Callback callback);
Python回调
from ctypes import *
# 定义回调类型
CALLBACK = CFUNCTYPE(None, c_int)
def progress_callback(progress):
print(f"Progress: {progress}%")
# 加载DLL
callback_dll = CDLL('callback.dll')
callback_dll.long_operation.argtypes = [CALLBACK]
callback_dll.long_operation.restype = None
# 调用
callback_func = CALLBACK(progress_callback)
callback_dll.long_operation(callback_func)
5. 错误处理
from ctypes import *
import sys
try:
mydll = CDLL('mydll.dll')
# 检查函数是否存在
if not hasattr(mydll, 'add'):
raise AttributeError("Function 'add' not found in DLL")
mydll.add.argtypes = [c_int, c_int]
mydll.add.restype = c_int
result = mydll.add(5, 3)
print(f"Result: {result}")
except OSError as e:
print(f"Failed to load DLL: {e}")
except AttributeError as e:
print(f"Function error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
6. 实际示例
C代码(编译为DLL)
// mathlib.c
#include <stdio.h>
__declspec(dllexport) int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
__declspec(dllexport) void greet(char* name) {
printf("Hello, %s!\n", name);
}
Python调用
from ctypes import *
# 加载DLL
mathlib = CDLL('./mathlib.dll')
# 设置函数原型
mathlib.factorial.argtypes = [c_int]
mathlib.factorial.restype = c_int
mathlib.greet.argtypes = [c_char_p]
mathlib.greet.restype = None
# 调用
result = mathlib.factorial(5)
print(f"5! = {result}")
mathlib.greet(b"Python User")
7. 其他调用方式
使用 cdll 加载
from ctypes import cdll
# 自动查找DLL
mydll = cdll.mydll # 在系统路径中的DLL
指定完整路径
from ctypes import CDLL
import os
dll_path = r'C:\full\path\to\your.dll'
mydll = CDLL(dll_path)
总结
- ctypes 是Python调用DLL的标准方法
- 必须正确设置
argtypes和restype - 注意数据类型转换,特别是字符串
- 结构体需要使用
Structure类定义 - 错误处理很重要,避免程序崩溃
Python调用DLL非常强大,可以让你利用现有的C/C++代码库,同时享受Python的易用性!
参考
https://blog.csdn.net/qq_29630271/article/details/74012465
更多推荐
所有评论(0)