You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不执行Py_CompileString生成的代码对象创建模块并绑定C++函数?

解决不执行Python代码先获取模块并嵌入C++函数的方案

要实现不执行Python代码先创建模块对象,再嵌入C++函数,最后执行模块代码的需求,你可以拆分步骤,绕过PyImport_ExecCodeModule(它会创建模块并立即执行代码),改用以下流程:


步骤1:创建空模块对象

先通过pybind11直接创建一个空模块,此时不会执行任何Python代码:

#include <pybind11/pybind11.h>
namespace py = pybind11;

// 创建空模块,命名为"my_module"
py::module mod = py::module::create("my_module");

// 可选:将模块注册到sys.modules,方便后续Python代码import
py::module sys = py::module::import("sys");
sys.attr("modules")["my_module"] = mod;

步骤2:嵌入C++函数到模块

直接用pybind11的def方法给空模块添加C++函数,此时模块已经存在,且未执行任何Python代码:

// 嵌入func1
mod.def("func1", []() {
    return "This is from C++ func1";
});

// 嵌入func2
mod.def("func2", [](int a, int b) {
    return a + b;
});

步骤3:编译Python代码为Code对象

用Py_CompileString将Python代码编译为Code对象(这一步不会执行代码,只是编译):

const char* myCode = R"(
print('Hello from Python code')
print('Call func1:', func1())
print('Call func2(2,3):', func2(2,3))
)";

// 编译代码,Py_file_input表示按文件模式编译
PyObject* codeObj = Py_CompileString(myCode, "<embedded_code>", Py_file_input);
if (!codeObj) {
    py::error_already_set();
    throw std::runtime_error("Failed to compile Python code");
}

步骤4:在模块上下文中执行Code对象

由于不能用pybind11::exec,可以直接调用Python C API的PyEval_EvalCode,在模块的命名空间中执行编译好的代码——此时模块已经有了嵌入的C++函数,Python代码可以直接调用:

// 获取模块的全局命名空间__dict__
py::dict modDict = mod.attr("__dict__");

// 在模块上下文中执行代码
PyEval_EvalCode(reinterpret_cast<PyCodeObject*>(codeObj), modDict.ptr(), modDict.ptr());

// 检查执行错误
if (PyErr_Occurred()) {
    py::error_already_set();
    throw std::runtime_error("Failed to execute Python code");
}

// 释放Code对象的引用
Py_DECREF(codeObj);

关键说明

  • py::module::create(底层封装PyModule_New)只会创建空模块,不会执行任何代码,满足你“先获取模块对象”的需求。
  • 先嵌入C++函数再执行Python代码,确保Python代码能直接调用这些函数。
  • 注册模块到sys.modules后,后续Python代码可以通过import my_module直接使用该模块及嵌入的函数。

内容的提问来源于stack exchange,提问作者qssh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:05:24