如何使用<double>boost::p ython通过引用将non-const std::vector传递给Python?
How to pass non-const std::vector<double> by reference to Python with boost::python?
我希望能够给出一个空的std::vector<double>&
作为Python函数的参数来填充它
Python文件Foo.py:
class Foo :
def bar(self, x) :
x.push_back(3.14)
foo = Foo()
C++代码:
Py_Initialize();
boost::python::object pyobj_main = boost::python::import("__main__");
boost::python::object glob = pyobj_main.attr("__dict__");
glob["std_vector_double"] = boost::python::class_< std::vector<double> >("std_vector_double").def(boost::python::vector_indexing_suite< std::vector<double> >());
boost::python::exec_file("Foo.py", glob, glob);
boost::python::object foo = glob["foo"];
std::vector<double> x;
foo.attr("bar")(x);
// Now x.size() == 1 and x[0] == 3.14
我知道这个代码不起作用,这只是我想做的。
最好的方法是什么
我的第一个想法是将我的x
封装为另一个类VectorWrapper
中的指针,但这看起来是一个丑陋的坏主意。。。
默认情况下,Boost.Python将创建一个副本,因为这是防止悬挂引用的最安全的操作方法。但是,通过使用boost::python::ptr()
或boost::ref()
,可以将对C++对象的引用传递给Python,同时保持C++中的所有权。C++代码应该保证C++对象的生存期至少与Python对象一样长。
foo.attr("bar")(boost::ref(x));
foo.attr("bar")(boost::python::ptr(&x));
上面的代码将构造一个引用x
的std_vector_double
Python对象。使用ptr()
时,如果指针为null,则生成的Python对象将为None
。
下面是一个基于原始问题的完整示例,演示了使用boost::ref()
传递对Python的引用。
#include <cmath> // std::abs
#include <limits> // std::numeric_limits::epsilon
#include <vector>
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
int main()
{
// Initialize Python.
setenv("PYTHONPATH", ".", 1);
Py_Initialize();
namespace python = boost::python;
try
{
// Create the __main__ module.
python::object main_module = python::import("__main__");
python::object main_namespace = main_module.attr("__dict__");
boost::python::class_<std::vector<double>>("std_vector_double")
.def(python::vector_indexing_suite<std::vector<double>>())
;
// Run the foo.py file within the main namespace.
python::exec_file("foo.py", main_namespace, main_namespace);
std::vector<double> x;
// Pass a reference (C++ maintains ownership) of 'x' to foo.bar().
main_namespace["foo"].attr("bar")(boost::ref(x));
// Verify 'x' was modified.
assert(x.size() == 1);
assert(std::abs(x[0] - 3.14) <= std::numeric_limits<double>::epsilon());
}
catch (const python::error_already_set&)
{
PyErr_Print();
return 1;
}
// Do not call Py_Finalize() with Boost.Python.
}
foo.py
的内容为:
class Foo:
def bar(self, x):
x.append(3.14)
foo = Foo()
相关文章:
- 尝试使用 std::vector<std::thread时出现静态断言失败错误>
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- 连接和压缩标准::vector<std::字符串的最佳方法>
- C++从 std::vector<std::function<中删除 std::function>>
- 如何在构造函数初始值设定项列表中使用 n 个元素初始化 std::vector<std::time_t>
- 如何使用 CUDA 将 std::vector<std::string> 复制到 GPU 设备
- 编译错误 std::vector<std::shared_ptr<T>>迭代器和擦除方法
- 将 std::vector<std::unique_ptr<T>> 移动到 std::vector<std::shared_ptr<T>>
- 如何从 boost::container::vector<std::string>::iterator 访问索引和对象?
- 使用 std::vector<std::future<int>> 和 std::async 启动几个线程时中止
- 为什么转置这个 std::vector<std::vector<std::string> > 这么慢?
- 是否有可能在没有复制的情况下传递 std::vector<int> 作为参数来获得 std::vector<std::array<int, 3>>?
- 在 boost::<double>asio::buffer 中使用像 std::vector<std::complex> 这样的参数
- 如何从 std::initializer_list<char const* 构建 std::vector<std::string>>
- 如何检查 std::vector<std::string> 的元素是否以某个子字符串开头?
- 在 std::vector<std::vector 中重新存储内部向量<TYPE>>
- 将 std::vector<std::string> 转换为 const char* const*
- 不能将结构push_back() 转换为 std::vector<std::shared_ptr<theStruct>> theVector
- SWIG:传递一个 std::vector< std::vector <double> >指向 python 的指针
- 将 std::vector<std::p air<const K, V>*> 转换为 std::vector<std::p air<const K, V>&g