Python调用C++

Python是一门及其优雅的语言,而C++是一门非常强大高效的语言。如何做到高效又不失优雅呢?最好的方式就是将二者结合。 Python是通过ctypes模块来调用C++的(严格地说是调用C的), 当然Python不止如此它还可以通过SWIG 调用其他语言, Java, Go … 都不在话下。而且通过Python/C API 在C++/C中也可以直接操作Python对象。 本文记录了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
#include <iostream>
#include <string>
#include <cstdlib>
#define LEN(arr) sizeof(arr)/sizeof(arr[0])

class Cbacken{
private:
void _swap(int *, int, int);
int _partition(int *, int, int);
void _quick_sort(int *, int, int);
public:
// 排序
void sort(int *arr, int n);
};

void Cbacken::_swap(int *arr, int i, int j){
int t;
t = *(arr+j);
*(arr+j) = *(arr+i);
*(arr+i) = t;
}
int Cbacken::_partition(int *arr, int low, int high){
int randint = rand()%high + low;
this->_swap(arr, randint, high);

int store_idx=low, i, j, privot= *(arr+high);
for (i=low; i<high; i++){
if (*(arr+i) < privot){
this->_swap(arr, i, store_idx);
store_idx++;
}
}
this->_swap(arr, store_idx, high);
return store_idx;
}

void Cbacken::_quick_sort(int *arr, int low, int high){
if (low < high){
int mid = this->_partition(arr, low, high);
this->_quick_sort(arr, low, mid-1);
this->_quick_sort(arr, mid+1, high);
}
}

void Cbacken::sort(int *arr, int n){
this->_quick_sort(arr, 0, n-1);
}

// 封装C接口
extern "C"{
// 创建对象
Cbacken* cbacken_new(){
return new Cbacken;
}
void cbacken_sort(Cbacken* cb, int *arr, int n){
cb->sort(arr, n);
}
}

代码中使用了快速排序来作为排序接口,由于ctypes接口仅支持C,故使用了extern “C” 告诉编译器修饰的变量和函数是按照C语言方式编译和连接的。

生成动态链接库

Windows下的.DLL, Linux下常用 .so 后缀标示的文件是动态链接文件。 pic

在此以Linux为例,以下语句生成动态链接库 For Linux $ g++ -shared -Wl,-soname,cbacken -o cbacken.so -fPIC cbacken.cpp For Mac $ g++ -shared -Wl,-install_name,cbacken.so -o cbacken.so -fPIC cbacken.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
# -*- coding: utf-8 -*-
import ctypes
# 指定动态链接库
lib = ctypes.cdll.LoadLibrary('./cbacken.so')

class Wrapper(object):
def __init__(self):
# 动态链接对象
self.obj = lib.cbacken_new()

def sort(self, lst):
n = len(lst)
# init arr
cb_ARR = ctypes.c_int * n
cb_arr = cb_ARR()
for i in range(n):
if not isinstance(lst[i], int):
raise ValueError("Only support Integer Array")

cb_arr[i] = lst[i]
# init int
cb_N = ctypes.c_int
cb_n = cb_N()
cb_n = n
# sort
lib.cbacken_sort(self.obj, cb_arr, cb_n)
nlst = [x for x in cb_arr]
return nlst

if __name__ == '__main__':
wp = Wrapper()
print(wp.sort([2, 1, 4, 3]))
# output [1, 2, 3, 4]
sean lee wechat
欢迎关注我的公众号!
感谢支持!