python调用C++ —— ctypes库尝试

python调用c++有很多种方法,今天我就来整理使用一下python中ctypes模块的用法。

网上可以找到很多关于ctypes的使用资料,但都不全:
1.类型介绍不完整
2.只有python传入c++参数
3.只有python接收c++返回
我就针对以上的问题,作一个比较全面的使用介绍吧。

使用很简单,各种拼拼凑凑,看代码就可以懂,就不多说了。

c++ 代码
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <string>
using namespace std;

typedef struct StructTest
{
char* name;
int age;
int score[3];
}StructTest, *StructPtr;

class TestLib
{
public:
int passInt(int a);
double passDouble(double d);
char passChar(char c);
char* passString(char* s);
StructTest passStruct(StructTest st);
StructPtr passStructPtr(StructPtr p);
StructPtr passStructArray(StructTest vst[], int size);
};

int TestLib::passInt(int a) {
cout << a << " in c++" << endl;
return a;
}

double TestLib::passDouble(double d) {
cout << d << " in c++" << endl;
return d;
}

char TestLib::passChar(char c) {
cout << c << " in c++" << endl;
return c;
}

char* TestLib::passString(char* s) {
cout << s << " in c++" << endl;
return s;
}

StructTest TestLib::passStruct(StructTest st) {
cout << st.name << " " << st.age << " " << st.score[2] << " in c++" << endl;
return st;
}

StructPtr TestLib::passStructPtr(StructPtr p) {
cout << p->name << " " << p->age << " " << p->score[2] << " in c++" << endl;
return p;
}

StructPtr TestLib::passStructArray(StructTest vst[], int size) {
cout << vst[0].name << " in c++" << endl;
cout << vst[1].name << " in c++" << endl;
return &vst[0];
}

extern "C" {
TestLib obj;

int passInt(int a) {
return obj.passInt(a);
}

double passDouble(double d){
return obj.passDouble(d);
}

char passChar(char c) {
return obj.passChar(c);
}

char* passString(char* s){
return obj.passString(s);
}

StructTest passStruct(StructTest st){
return obj.passStruct(st);
}

StructPtr passStructPtr(StructPtr p){
return obj.passStructPtr(p);
}

StructPtr passStructArray(StructTest vst[], int size){
return obj.passStructArray(vst, size);
}
}
// generate it into lib
// g++ -o libTest.so -shared -fPIC cppLib.cpp
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
__author__ = 'xidui'
import ctypes
so = ctypes.cdll.LoadLibrary
lib = so('./libTest.so')

# passInt
print('passInt')
print(lib.passInt(100))
print('--------------------')

# passDouble
print('passDouble')
lib.passDouble.restype = ctypes.c_double
print(str(lib.passDouble(ctypes.c_double(1.23))) + ' in python')
print('--------------------')

# passChar
print('passChar')
lib.passChar.restype = ctypes.c_char
print(str(lib.passChar(ctypes.c_char(65))) + ' in python') # 'A'
print(str(lib.passChar(ctypes.c_char(b'A'))) + ' in python') # 'A'
print('--------------------')

# passString
print('passString')
lib.passString.restype = ctypes.c_char_p
print(str(lib.passString(ctypes.c_char_p(b'abcde'))) + ' in python') # 这里一定要加b
print('--------------------')

# passStruct
print('passStruct')
class Struct(ctypes.Structure):
_fields_ = [('name', ctypes.c_char_p),
('age', ctypes.c_int),
('score', ctypes.c_int * 3)]
lib.passStruct.restype = Struct
array = [1, 2, 3]
st = lib.passStruct(Struct(b'xidui', 10, (ctypes.c_int * 3)(*array)))
# p = lib.passStruct(Struct(b'xidui', 10, (ctypes.c_int * 3)(1, 2, 3)))
print(str(st.name) + ' ' + str(st.age) + ' ' + str(st.score[2]) + ' in python')
print('--------------------')

# passStructPointer
print('passStructPointer')
lib.passStructPtr.restype = ctypes.POINTER(Struct)
lib.passStructPtr.argtypes = [ctypes.POINTER(Struct)] # 这行不加,程序会宕
p = lib.passStructPtr(Struct(b'xidui', 10, (ctypes.c_int * 3)(*array)))
print(str(p.contents.name) + ' ' + str(p.contents.age) + ' ' + str(p.contents.score[2]) + ' in python')
print('--------------------')

# passStructArray
print('passStructArray')
lib.passStructArray.restype = ctypes.POINTER(Struct)
lib.passStructArray.argtypes = [ctypes.ARRAY(Struct, 2), ctypes.c_int]
array = [Struct(b'xidui1', 10, (ctypes.c_int * 3)(1, 2, 3)),
Struct(b'xidui2', 10, (ctypes.c_int * 3)(1, 2, 3))]
p = lib.passStructArray(ctypes.ARRAY(Struct, 2)(*array), 2)
print(str(p.contents.name) + ' ' + str(p.contents.age) + ' ' + str(p.contents.score[2]) + ' in python')
print('--------------------')

大家想要别的类型,可以在留言板中添加,我会尽快更新到博客中