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

如何通过Boost Python向Python模块添加类并在eval中调用?

问题:Boost.Python中向eval环境添加C++类的报错解决

我已经实现了向Python模块添加简单C函数并通过eval()调用的功能,但尝试添加C类时,执行boost::python::exec("import hello")或后续eval语句都会触发python::throw_error_already_set()异常,求正确的实现方式。

成功添加函数的示例代码

#include <boost/python.hpp>

static int myFunc()
{
    return 3;
}

int main()
{
    auto main_module = boost::python::import("__main__");
    auto main_namespace = main_module.attr("__dict__");
    main_namespace["myFunc"] = boost::python::object(&myFunc);
    auto evalResult = boost::python::eval("myFunc()", main_namespace);
    assert((int)boost::python::extract<int>(evalResult) == 3);
}

尝试添加类的报错代码

#include <boost/python.hpp>

struct World
{
    int myFunc()
    {
        return 3;
    }
};

BOOST_PYTHON_MODULE(hello)
{
    boost::python::class_<World>("World").def("myFunc", &World::myFunc);
}
 
int main()
{
    auto main_module = boost::python::import("__main__");
    auto main_namespace = main_module.attr("__dict__");

    boost::python::exec("import hello");
    auto evalResult = boost::python::eval("hello.World().myFunc()", main_namespace);
    assert((int)boost::python::extract<int>(evalResult) == 3);
}

问题原因及解决方法

原因

用BOOST_PYTHON_MODULE定义的模块默认是作为动态库加载的,直接在宿主程序里执行import hello会找不到这个模块——因为模块没有被注册到Python解释器中,也没有对应的动态库文件。

解决方法

有两种可行的实现方式:

方式1:直接将类注册到当前命名空间

不需要定义独立的BOOST_PYTHON_MODULE,直接在main函数里把C++类注册到main_namespace中,操作逻辑和添加普通函数一致:

#include <boost/python.hpp>

struct World
{
    int myFunc()
    {
        return 3;
    }
};

int main()
{
    auto main_module = boost::python::import("__main__");
    auto main_namespace = main_module.attr("__dict__");

    // 直接将World类注册到当前命名空间
    boost::python::class_<World>("World").def("myFunc", &World::myFunc);
    // 也可以显式绑定到main_namespace
    // main_namespace["World"] = boost::python::class_<World>("World").def("myFunc", &World::myFunc);

    auto evalResult = boost::python::eval("World().myFunc()", main_namespace);
    assert((int)boost::python::extract<int>(evalResult) == 3);
}

方式2:手动注册模块到Python解释器

如果一定要保留BOOST_PYTHON_MODULE的模块定义,可以在main函数中手动调用模块的初始化函数,将模块注册到Python解释器中:

#include <boost/python.hpp>

struct World
{
    int myFunc()
    {
        return 3;
    }
};

BOOST_PYTHON_MODULE(hello)
{
    boost::python::class_<World>("World").def("myFunc", &World::myFunc);
}
 
int main()
{
    Py_Initialize(); // 确保Python解释器完成初始化

    auto main_module = boost::python::import("__main__");
    auto main_namespace = main_module.attr("__dict__");

    // 手动调用模块初始化函数,注册hello模块
    inithello(); // 函数名对应BOOST_PYTHON_MODULE(hello)生成的初始化入口

    auto evalResult = boost::python::eval("hello.World().myFunc()", main_namespace);
    assert((int)boost::python::extract<int>(evalResult) == 3);

    Py_Finalize();
}

注意:这种方式下,编译时需要确保链接器能找到inithello()函数,部分编译器可能需要显式导出该函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:57:52