在 python 代码中植入 c++ 代码
创建于:2025年4月12日
创建于:2025年4月12日
在 python 代码中植入 c++ 代码
在 Python 中“直接植入”C++ 代码并不是像在同一个文件里写两种语言代码那样简单,因为 Python 解释器并不能原生执行 C++ 代码。通常来说,我们需要借助以下几种方法来让 Python 能调用 C/C++ 写的逻辑:
ctypes
、Cython
、pybind11
、cppimport
等)下面给出几种常见方式的示例。
Python 官方支持编写 C/C++ 扩展模块,然后通过 import
的形式在 Python 中使用。整体思路是先将 C++ 代码编译成共享库(.so 文件或 .pyd 文件),再用 Python 导入。
假设我们有以下文件结构:
textmy_extension/ ├── setup.py ├── mymodule.cpp └── test.py
mymodule.cpp
:用 C++ 编写的扩展模块实现setup.py
:用于编译、安装扩展模块test.py
:测试脚本cpp#include <Python.h> // 声明一个 C++ 函数,用来给 Python 调用 static PyObject* hello_from_cpp(PyObject* self, PyObject* args) { // 不需要从 args 中获取参数,这里只是返回一个字符串 return Py_BuildValue("s", "Hello from C++!"); } // 定义本模块中包含的方法表 static PyMethodDef MyMethods[] = { {"hello_from_cpp", hello_from_cpp, METH_VARARGS, "Say hello from C++"}, {NULL, NULL, 0, NULL} // 哨兵,用于结束方法表 }; // 定义模块 static struct PyModuleDef mymodule = { PyModuleDef_HEAD_INIT, "mymodule", // 模块名 "Example module that says hello from C++", -1, // 全局状态(-1表示不支持子解释器) MyMethods }; // 模块初始化函数,函数名固定为 PyInit_<模块名> PyMODINIT_FUNC PyInit_mymodule(void) { return PyModule_Create(&mymodule); }
pythonfrom setuptools import setup, Extension # 定义要编译的扩展模块 module = Extension( 'mymodule', # 模块名,import 时就用这个名字 sources=['mymodule.cpp'] # 源文件 ) setup( name='mymodule', version='1.0', description='Example C++ extension for Python', ext_modules=[module], )
在 my_extension/
目录下执行:
bashpython setup.py build
这条命令会在 build
目录生成编译后的扩展文件(通常是类似 mymodule.cpython-39-darwin.so
或 .pyd
的文件,视操作系统/解释器版本而定)。
安装到本地 Python 环境,可以执行:
bashpython setup.py install
测试时,在 test.py
中使用:
pythonimport mymodule print(mymodule.hello_from_cpp())
如果输出 Hello from C++!
,就说明扩展模块工作正常。
ctypes
调用已编译的 C/C++ 共享库如果你已经有一个现成的 C++ 动态库(如 .so
、.dll
),或者你可以把 C++ 代码编译成动态库(也可以是 C++17/20 的代码),可以使用 Python 内置库 ctypes
来加载并调用。
假设我们先写一个简单的 C++ 文件 my_lib.cpp
:
cpp#include <string> // 为了兼容 C 调用方式,需要 extern "C"。 extern "C" { // 假设暴露一个函数返回一个字符串 const char* get_greeting() { return "Hello from my_lib!"; } }
然后编译生成动态库(在 Linux/Mac 下):
bashg++ -shared -fPIC my_lib.cpp -o libmylib.so
在 Windows 下则会生成 .dll
。
有了 libmylib.so
(或 mylib.dll
)之后,可以在 Python 中用 ctypes
调用:
pythonimport ctypes import os # 如果文件名是 libmylib.so,在 Linux/Mac 下这样写 lib_path = os.path.join(os.getcwd(), "libmylib.so") # Windows 下类似: lib_path = "mylib.dll" my_lib = ctypes.CDLL(lib_path) # 声明函数返回类型(如果需要) my_lib.get_greeting.restype = ctypes.c_char_p # 调用函数 greeting = my_lib.get_greeting() print(greeting.decode("utf-8"))
正常情况下会打印出 Hello from my_lib!
.
pybind11 是一个非常简洁且流行的 C++11/14/17 绑定库,能极大简化在 Python 和 C++ 之间的调用和数据类型转换。
textmy_pybind/ ├── setup.py ├── example.cpp └── test.py
cpp#include <pybind11/pybind11.h> namespace py = pybind11; // 简单的 C++ 函数 int add(int i, int j) { return i + j; } PYBIND11_MODULE(example, m) { // 模块名:example m.doc() = "pybind11 example plugin"; // 模块文档 m.def("add", &add, "A function which adds two numbers"); }
要想通过 setuptools
来编译,需要先确保系统装有 pybind11
库(可以先 pip install pybind11
),再编写编译脚本:
pythonimport os import sys import pybind11 from setuptools import setup, Extension from setuptools.command.build_ext import build_ext # 定义扩展模块 ext_modules = [ Extension( 'example', # 生成的模块名 ['example.cpp'], include_dirs=[ pybind11.get_include() ], language='c++' ), ] setup( name='example', version='0.1', ext_modules=ext_modules, cmdclass={'build_ext': build_ext}, )
然后执行编译:
bashpython setup.py build
编译成功后,会生成 example
模块(.so
或 .pyd
文件)。
pythonimport example result = example.add(3, 5) print(result) # 预期输出:8
Cython 也是一种常见方法。它允许你在 .pyx
文件里写“近似 Python 语法”的代码,再通过 Cython 将其转为 C/C++,最后编译成扩展模块。对于需要高性能或直接调用 C/C++ 函数库的场景,Cython 也非常常用。
简要步骤:
pip install cython
example.pyx
文件,写含有 C 函数调用/声明的代码setup.py
配合 cythonize
把 .pyx
编译为扩展import example
后即可调用cppimport
(在线编译并内联调用 C++)如果你想在 Python 文件内部“看上去写 C++ 代码”,并在导入时自动完成编译,可使用 cppimport。
示例:
python# 先 pip install cppimport import cppimport # 假设当前目录有一个 example.cpp 文件: # int add(int x, int y) { return x + y; } # 在 Python 中写一个 “.py” 文件: import cppimport example = cppimport.imp("example") # 这会自动编译并导入 example.cpp 生成的扩展 print(example.add(2, 3)) # 调用 C++ 函数,输出 5
或者甚至可以把 C++ 代码直接写在 .py
文件中,在文件开头加一个特殊的注释来让 cppimport
识别,然后自动完成“边编译边导入”,不过相对不太常见(适合快速试验)。
ctypes
、cffi
等方式加载。cppimport
让你能在 Python 中直接写几行 C++ 代码并即时编译,适合小规模测试或原型。所以,并没有一种“在 .py 文件内部直接插入 C++ 代码就能执行”的方法,而是通过上述工具或扩展机制完成“Python 调用 C++”。根据你的应用场景选择合适的方法就可以实现“在 Python 中使用 C++ 逻辑”。