使用c++扩展python
简介
c++可以编写python的扩展库。
- Extending Python with C or C++ — Python 3.11.4 documentation
开发环境
linux 下需要安装python3-dev
CMAKE编写
这里给出test.cpp编写的python模块和测试用 的test.py
编译与执行
1mkdir build
2
3cmake -S . -B ./build
4
5cmake --build ./build
6
7python3 test.py
1cmake_minimum_required(VERSION 3.12) # 3.12才可以find_package(python)
2project(test_cp)
3
4find_package (Python REQUIRED Interpreter Development)
5
6set(test_cpp_demo_name "test_cpp") # 定义一个库的名字,同时作为py模块的名字
7add_definitions(-DPY_MODULE_NAME_STR="${test_cpp_demo_name}")
8add_definitions(-DPY_MODULE_NAME=PyInit_${test_cpp_demo_name})
9
10
11add_library(${test_cpp_demo_name} SHARED test.cpp)
12set_target_properties(
13 ${test_cpp_demo_name}
14 PROPERTIES
15 PREFIX "" # 输出前缀没有了
16 OUTPUT_NAME ${test_cpp_demo_name}.cpython-310-x86_64-linux-gnu # 注意后边的python版本、平台版本、编译器组织
17)
18target_include_directories(${test_cpp_demo_name} PRIVATE
19 ${Python_INCLUDE_DIRS})
20
21target_link_directories(${test_cpp_demo_name} PRIVATE
22 ${Python_LIBRARY_DIRS})
23
24target_link_libraries(${test_cpp_demo_name} PRIVATE
25 ${Python_LIBRARIES})
TEST.CPP
具体可以参考上边给出的链接
1#include "Python.h"
2
3// 起一个命名空间
4namespace test_cpp {
5constexpr int N = 1000;
6int f[N];
7bool flag = false;
8int Fib_impl(int n) {
9 if (flag && 0 <= n && n < N) {
10 return f[n];
11 }
12 f[1] = 1;
13 for (int i = 2; i < N; ++i) {
14 f[i] = f[i - 1] + f[i - 2];
15 }
16 flag = true;
17 return f[n];
18}
19} // namespace test_cpp
20
21// 给python导出接口
22static PyObject *Fib(PyObject * /* unused module reference */, PyObject *o) {
23 int n = PyLong_AsLong(o);
24 int fn = test_cpp::Fib_impl(n);
25 return Py_BuildValue("i", fn);
26}
27
28//定义python模块中有哪些函数
29static struct PyMethodDef test_cpp_methods[] = {
30 {"fast_fib", Fib, METH_O, "fast fib"},
31 // Terminate the array with an object containing nulls.
32 {nullptr, nullptr, 0, nullptr}};
33
34// 定义模块
35static struct PyModuleDef test_cpp_module = {
36 PyModuleDef_HEAD_INIT,
37 PY_MODULE_NAME_STR, /* name of module */ // python里可以import 这个名字
38 nullptr, /* module documentation, may be NULL */
39 -1, /* size of per-interpreter state of the module,
40 or -1 if the module keeps state in global variables. */
41 test_cpp_methods
42 };
43//定义模块的初始化函数,import之后会自动执行
44
45
46// .so的名字要和这个函数的名字、和PyModuleDef里的name对齐
47PyMODINIT_FUNC PY_MODULE_NAME(void) {
48 PyObject *m;
49 m = PyModule_Create(&test_cpp_module);
50 if (m == NULL)
51 return NULL;
52 return m;
53}
PYTHON使用
1import sys
2# sys.path.append("./build/lib.linux-x86_64-3.10")
3sys.path.append("./build")
4import test_cpp
5
6a = test_cpp.fast_fib(10);
7print(a)