Pyxcpp混合调用
使用Python调用Cpp
ctypes
ctypes是Python的一个外部函数库,它提供了与C语言兼容的数据类型,允许调用动态链接库中的函数。
使用cdll加载动态链接库
假设有一个cpp文件dyna.cpp
:
1
2
3
4
5
6
7
8
9
10
11
12
extern "C"{
int add(int, int);
}
int add(int a, int b){
return a + b;
}
// extern等价写法:
extern "C" int minus(int a, int b){
return a - b;
}
注意:由于cpp为实现多态,在编译时会将函数名进行重命名,因此需要使用
extern "C"
来声明避免这种情况。
并将其编译为动态链接库dyna.so
:
1
g++ -shared -fPIC dyna.cpp -o dyna.so
那么可在Python中调用:
1
2
3
4
5
6
7
from ctypes import cdll
dyna_lib = cdll.LoadLibrary("./dyna.so")
print(dyna_lib.add(1, 2))
# >>> 3
print(dyna_lib.minus(1, 2))
# >>> -1
使用c++数据类型/指针/数组
- 使用
c_int
,c_double
,c_char_p
等数据类型
ctypes 提供了一些与C语言数据类型对应的Python数据类型,如
c_int
,c_double
,c_char_p
等。
详见支持的数据类型
1
2
3
4
5
6
import ctypes
a = ctypes.c_int(1) # int
b = ctypes.c_double(1.0) # double
c = ctypes.c_char_p(b"hello") # char*
# ...
- 使用
pointer
指针
ctypes 提供了
pointer
函数用于获取指针。
1
2
3
4
5
6
import ctypes
a = ctypes.c_int(1)
b = ctypes.pointer(a) # b为a的指针
print(b.contents)
# >>> c_int(1)
- 使用
c_int * n
数组
创建数组类型的推荐方式是使用一个类型乘以一个正数:
1
2
3
4
5
import ctypes
arr = (ctypes.c_int * 3)(1, 2, 3)
print(arr[0], arr[1], arr[2])
# >>> 1 2 3
使用结构体
ctypes 提供了
Structure
类用于创建结构体。
假设有一个cpp文件dyna.cpp
:
1
2
3
4
5
6
7
8
9
10
11
12
13
struct Point{
int x;
int y;
};
extern "C"{
Point get_point(){
Point p;
p.x = 1;
p.y = 2;
return p;
}
}
并将其编译为动态链接库dyna.so
:
1
g++ -shared -fPIC dyna.cpp -o dyna.so
那么可在Python中调用:
1
2
3
4
5
6
7
8
9
10
import ctypes
class Point(ctypes.Structure):
_fields_ = [("x", ctypes.c_int), ("y", ctypes.c_int)]
dyna_lib = ctypes.CDLL("./dyna.so")
dyna_lib.get_point.restype = Point
p = dyna_lib.get_point()
print(p.x, p.y)
# >>> 1 2
cython
Cython是一个Python的扩展,它允许在Python中使用C语言的数据类型和函数。 实现混合编写,即在Python中调用C语言的函数。
以下是一个简单的例子:
1
cimport numpy as np
pybind11
pybind11是一个只有头文件的轻量级库,实现C++到Python的绑定
安装
- 直接pip安装
1
pip install pybind11
- 使用git submodule集成
1
2
git submodule add /path/to/pybind11
git submodule update --init
使用
简单示例:
1
2
3
4
5
6
7
8
9
10
#include <pybind11/pybind11.h>
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(example, m) { // 模块名为example, m为模块对象
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("add", &add, "A function which adds two numbers");
}
然后编译为动态链接库:
1
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
在Python中调用:
1
2
3
import example
print(example.add(1, 2))
# >>> 3L
本文由作者按照 CC BY 4.0 进行授权