cython调用c++动态库示例
- cpp代码暴露的函数如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef struct can_frame{
int can_id;
uint8_t can_data[8];
}can_frame;
typedef struct singal
{
int start;
int length;
float scale;
float offest;
float min_val;
float max_val;
bool little_order;
bool is_unsigned;
char* name;
}singal;
extern "C" {
float decode(singal s, can_frame t);
void add_dbc(char* dbc_path);
char* decode_message(can_frame t, bool use_val_table=true);
}
- 在cmake中通过 add_library(test_can SHARED can_parser.cpp) 导出libtest_can.so,至此动态库导出完成。接下来python调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
## 导入ctypes
from ctypes import *
## 加载动态库
decode_dll = cdll.LoadLibrary("/home/cao/CLionProjects/pcv/build/lib/libtest_can.so")
## 定义结构体,同cpp定义一致,左侧为变量名,右侧为类型。其中c语言与ctypes的类型转换见末尾
class singal(Structure):
_fields_ = [
("start", c_int),
("length", c_int),
("scale", c_float),
("offest", c_float),
("min_val", c_float),
("max_val", c_float),
("little_order", c_bool),
("is_unsigned", c_bool),
("name", c_char_p)
]
class can_frame(Structure):
_fields_ = [
("can_id", c_int),
("can_data", c_ubyte*8)
]
## 调用add_dbc函数
name = c_char_p(bytes("./dbc/QZ_x1q_20200224.dbc", "utf-8")) # str -> bytes -> c_char_p
decode_dll.add_dbc(name)
## 调用decode
can_id = 10086
can_data = [0, 1, 2, 3, 4, 5, 6, 7]
data = (c_ubyte*8)(*can_data)
c = can_frame(can_id, data)
s = singal(8, 12, 0.0625, 0, 0, 250, True, True, c_char_p(bytes("test", "utf-8")))
decode_dll.decode.restype = c_float
px = decode_dll.decode(s, c)
## 调用decode_message
decode_dll.decode_message.restype = c_char_p # 设置返回类型
res = decode_dll.decode_message(c)
res = res.decode() # bytes -> str
- 附图
官方链接
基础数据类型¶
ctypes
定义了一些和C兼容的基本数据类型:
ctypes 类型 |
C 类型 |
Python 类型 |
---|---|---|
|
bool (1) |
|
|
单字符字节对象 |
|
|
单字符字符串 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
整型 |
|
|
浮点数 |
|
|
浮点数 |
|
|
浮点数 |
|
|
字节串对象或 |
|
|
字符串或 |
|
|
int 或 |