商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > c python boost.python_将指针从C传递给Python / w boost python?

c python boost.python_将指针从C传递给Python / w boost python?

  发布于2026-07-07 阅读(0)

扫一扫,手机访问

在使用Boost.Python进行C++与Python交互时,有一个很常见的需求:在C++侧生成一个大整数向量,然后让Python侧直接访问它,避免不必要的内存拷贝。理想很丰满,但实际操作中可能会被一些细节绊倒——比如,下面这个例子。

c python boost.python_将指针从C传递给Python / w boost python?

在C++中,定义了一个返回vector*的函数,并通过Boost.Python暴露出去:

BOOST_PYTHON_MODULE(myModule)
{
    class_>("vectorInt").def(vector_indexing_suite>());
    def("ReturnVectorPtr", ReturnVectorPtr, return_value_policy());
}

vector* ReturnVectorPtr()
{
    return new vector();
}

接着在Python中调用:

import myModule
myModule.ReturnVectorPtr()

结果——Python直接崩溃了。而且即便没有存储返回值,崩溃依然发生。问题出在哪?

其实关键就在 return_value_policy 的选择上。return_internal_reference 意味着返回一个指向内部对象的引用,但这个指针是由 new 分配的,Python 并不会自动管理它的生命周期。更糟糕的是,这个策略要求被引用的对象必须有一个持久的持有者,否则一旦引用失效,后续访问就会导致段错误。

另一种常见做法是避免直接返回指针,而是通过修改传入的向量来影响Python侧。比如下面的写法:

BOOST_PYTHON_MODULE(myModule)
{
    class_>("vectorInt").def(vector_indexing_suite>());
    def("ModifyVectorInPlace", ModifyVectorInPlace);
}

void ModifyVectorInPlace(vector& data)
{
    // Modify data...
    return;
}

然后Python端:

import myModule
vectorInt = myModule.vectorInt()
myModule.ModifyVectorInPlace(vectorInt)

这个方案看似没问题——直接传递引用,原地修改。但结果仍然是崩溃,连堆栈都指向了 invoke.hpp 中的段错误。

具体崩溃点出现在 invoke 函数内部:

template <...>
inline PyObject* invoke(invoke_tag_, RC const& rc, F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, AC, & ac) )
{
    return rc(f( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT) ));
}

从堆栈看,问题出在 rc(f(...)) 这一步。通常是因为 f 返回的对象类型与 rc(result converter)预期的不匹配,或者转换过程中引用了已经释放的内存。具体到 ModifyVectorInPlace 这个例子,vector& 作为参数,Boost.Python 会尝试将Python端的 vectorInt 对象转换成C++引用。如果 vectorInt 的包装没有正确持有底层C++对象,或者引用传递过程中发生了拷贝,都可能导致后续操作访问无效地址。

总结来看,要安全地在C++和Python之间传递大数据结构,有几个要点需要警惕:

  • 避免使用 return_internal_reference 来返回新建的裸指针——Python不负责 delete,内存泄露;而且引用容易被悬挂。
  • 对于“原地修改”模式,要确保传入的对象在Python侧有稳定的生命周期,并且Boost.Python的引用语义正确地映射到了底层对象,而不是创建了一个临时副本。
  • 如果确实需要传递大数据且避免拷贝,更推荐使用 shared_ptr> 配合 return_value_policy>>> 或直接暴露成Python的 array.array / memoryview,让底层共享同一块内存。

上面两个例子崩溃的根本原因,一个是指针生命周期管理不当,另一个是引用传递时对象状态不一致。理解这些细节后,再处理类似的跨语言数据传递就会从容很多。

本文转载于:https://blog.csdn.net/weixin_39887748/article/details/113377347 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注