概述
python ctypes
Table of Contents
- 1 Python中调用C语言库
1 Python中调用C语言库
Python中提供了ctypes标准库,用来调用C语言库中的函数。
- 加载dll C语言函数存在不同的调用约定,常见的有stdcall和cdecl,这两种调用约定在Python中的调用函数需要区分:
- stdcall的加载方式: dll = windll.LoadLibrary("dllpath") dll = WinDLL("dllpath")
- cdecl的加载方式: dll = cdll.LoadLibrary("dllpath") dll = CDLL("dllpath")
- 调用函数,传入参,返回值 C函数通过参数读取值,做处理后通过返回值传回。
#include <stdlib.h> // file add.c #include <stdio.h> int add(const int a, const int b) { return a+b; }
把C函数编译为.so库,执行一下命令: gcc -shared -fPIC -o libadd.so add.c
from ctypes import * dll = CDLL("./libadd.so") print("add(1,2) = ", dll.add(1, 2))
执行Python命令,查看执行情况: python3 ./add.py add(1,2) = 3
- C函数通过参数传出值,即参数是指针的情况 C语言指针概念在ctypes中用pointer对应,如下示例:
#include <stdlib.h> // file add.c #include <stdio.h> int add(const int a, const int b) { return a+b; } int add2(const int a, const int b, int *c) { if (NULL != c) *c = a+b; return a+b; }
add2函数传入指针,并可通过指针输出值。 python调用函数如下:
from ctypes import * dll = CDLL("./libadd.so") print("add(1,2) = ", dll.add(1, 2)) out = c_int(0) ptr = pointer(out) out.value = 100 print("out.value = ", out.value) dll.add2(2,3,ptr) print("add2(2, 3) = ", out.value)
python3 ./add.py add(1,2) = 3 out.value = 100 add2(2, 3) = 5
- 参数是结构体指针 结构体通过继承Structure类实现,各字段通过field定义,示例如下:
typedef struct { int x; int y; } Point; int add3(const Point a, const Point b, Point *c) { if (NULL == c) return 255; c->x = a.x + b.x; c->y = a.y + b.y; return 0; }
Python中的定义如下:
class Point(Structure): _fields_ = ("x", c_int), ("y", c_int) def __repr__(self): return "(%d, %d)" % (self.x, self.y) p1 = Point(1,2) p2 = Point(5, 8) p3 = Point(0,0) ptr_p3 = pointer(p3) dll.add3(p1,p2,ptr_p3) print("add3(p1,p2) = ", p3)
其中_repr_是python的内置函数,这个是类的展示函数,相当于java语言中的toString()函数。
- 入参char*指针
int pr(const char *name, char *out) { printf("Hello, %sn", name); sprintf(out, "Hello, %sn", name); return 0; }
- 方法1
sbuf = create_string_buffer(b'robin') out = create_string_buffer(100) dll.pr(sbuf, out) print("1--", out.value)
- 方法2
sbuf2 = b'
- 方法1