Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用boost::python向量索引套件包装std::向量 我在使用Python绑定(使用Booo::Python)表示一个C++库,它表示存储在一个文件中的数据。我的大多数半技术用户将使用Python与之交互,因此我需要使其尽可能具有Python风格。但是,我也会使用C++程序员使用API,所以我不想在C++方面妥协来适应Python绑定。_Python_C++_Boost Python - Fatal编程技术网

使用boost::python向量索引套件包装std::向量 我在使用Python绑定(使用Booo::Python)表示一个C++库,它表示存储在一个文件中的数据。我的大多数半技术用户将使用Python与之交互,因此我需要使其尽可能具有Python风格。但是,我也会使用C++程序员使用API,所以我不想在C++方面妥协来适应Python绑定。

使用boost::python向量索引套件包装std::向量 我在使用Python绑定(使用Booo::Python)表示一个C++库,它表示存储在一个文件中的数据。我的大多数半技术用户将使用Python与之交互,因此我需要使其尽可能具有Python风格。但是,我也会使用C++程序员使用API,所以我不想在C++方面妥协来适应Python绑定。,python,c++,boost-python,Python,C++,Boost Python,图书馆的大部分将由容器构成。为了让python用户更直观,我希望他们的行为类似于python列表,即: # an example compound class class Foo: def __init__( self, _val ): self.val = _val # add it to a list foo = Foo(0.0) vect = [] vect.append(foo) # change the value of the *original* ins

图书馆的大部分将由容器构成。为了让python用户更直观,我希望他们的行为类似于python列表,即:

# an example compound class
class Foo:
    def __init__( self, _val ):
        self.val = _val

# add it to a list
foo = Foo(0.0)
vect = []
vect.append(foo)

# change the value of the *original* instance
foo.val = 666.0
# which also changes the instance inside the container
print vect[0].val # outputs 666.0
测试设置 在我的测试设置中,这会产生与纯Python相同的输出:

Foo = 666.0
vector[0] = 666.0
向量的方式

使用向量直接给出C++上一个漂亮的干净设置。但是,结果与纯Python的行为方式不同

BOOST_PYTHON_MODULE( test ) {
    // wrap Foo
    boost::python::class_< Foo >("Foo", boost::python::init<double>())
        .def_readwrite("val", &Foo::val);

    // wrap vector of Foos
    boost::python::class_< std::vector < Foo > >("FooVector")
        .def(boost::python::vector_indexing_suite<std::vector< Foo > >());
}
这是“错误的”-更改原始实例不会更改容器内的值

我希望我不要想要太多 有趣的是,无论我使用两种封装中的哪一种,这段代码都是有效的:

footwo = vect[0]
footwo.val = 555.0
print vect[0].val
这意味着boost::python能够处理“伪共享所有权”(通过其by_代理返回机制)。在插入新元素时,有没有办法达到同样的效果

但是,如果答案是否定的,我希望听到其他建议——Python工具包中是否有一个示例,其中实现了类似的集合封装,但不作为Python列表


非常感谢您阅读本文:)

不幸的是,答案是否定的,你不能做你想做的事。在python中,一切都是指针,列表是指针的容器。共享指针的C++向量工作,因为底层数据结构或多或少等同于Python列表。您所要求的是让分配的内存的C++向量像指针的指针,这是不可能完成的。

让我们看看Python列表中发生了什么,用C++等效伪代码:

foo = Foo(0.0)     # Foo* foo = new Foo(0.0)
vect = []          # std::vector<Foo*> vect
vect.append(foo)   # vect.push_back(foo)
这里,
vect[0]
有自己分配的内存,是*foo的副本。从根本上说,不能使vect[0]与*foo具有相同的内存

另一方面,在使用
std::vector
时,请注意对
footwo
的寿命管理:


后续追加可能需要移动为向量分配的存储,并且可能使footwo无效(&vect[0]可能会更改)。

由于语言之间的语义差异,当涉及集合时,通常很难将单个可重用解决方案应用于所有场景。最大的问题是,Python集合直接支持引用,C++集合需要间接级别,比如通过<代码> SyddypTr> /Cord>元素类型。如果没有这种间接性,C++集合将不能支持与Python集合相同的功能。例如,考虑两个引用同一对象的索引:

s=Spam()
垃圾邮件=[]
垃圾邮件。附加(个)
垃圾邮件。附加(个)

没有指针类型的元素类型,C++集合不能有两个索引引用同一个对象。然而,根据使用和需求,可能有选项允许Python用户使用Python接口,同时仍然保持C++的一个实现。

  • 最为python的解决方案是使用自定义转换器,它将Python可重复对象转换为C++集合。有关实现细节,请参见答案。如果选择:
    • 该系列的元素复制成本低廉
    • < L> > C++函数仅在rVales类型(即:代码> STD::vector < /COD> >或 COSTSTST:::vector和< />代码>中运行。此限制阻止C++对Python集合或其元素进行更改。
  • 增强功能,尽可能多地重用功能,例如用于安全处理索引删除和基础集合重新分配的代理:
    • 使用自定义对象公开模型,该自定义对象用作智能指针,并委托给从
      vector\u index\u suite
      返回的实例或元素代理对象
    • Monkey修补将元素插入集合的集合方法,以便将自定义
      HeldType
      设置为委托给元素代理

将类公开给Boost.Python时,
HeldType
是嵌入到Boost.Python对象中的对象类型。访问wrapped types对象时,Boost.Python调用
HeldType
。下面的
object\u holder
类提供了将句柄返回到其拥有的实例或元素代理的功能:

将委托给python的简短智能指针类型 ///对象(如果已设置)。 模板 类对象持有者 { 公众: 类型定义T元素_类型; 对象固定器(元素类型*ptr) :ptr_(ptr), 对象_uuz() {} 元素类型*get()常量 { 如果(!object_u.is_none()) { 返回boost::python::extract(object_)(); } 返回ptr_10;ptr_10;.get():NULL; } 无效重置(boost::python::object) { //验证对象是否包含所需的元素。 boost::python::提取提取器(对象); 如果(!extractor.check())返回; 对象=对象; ptr_.reset(); } 私人: boost::共享的ptr ptr; boost::python::object\uuz; }; ///@brief Helper函数用于从中提取指向的对象 ///一个物体的支架。Python将通过ADL使用它。 模板 T*get_指针(常量对象保持器和保持器) { 返回holder.get(); } 在支持间接寻址的情况下,唯一剩下的就是修补集合以设置
对象\u持有者
。支持这一点的一种干净且可重用的方法是使用。这是一个通用接口,允许对
对象进行非侵入式扩展。因为
Foo = 666.0
vector[0] = 0.0
footwo = vect[0]
footwo.val = 555.0
print vect[0].val
foo = Foo(0.0)     # Foo* foo = new Foo(0.0)
vect = []          # std::vector<Foo*> vect
vect.append(foo)   # vect.push_back(foo)
foo = Foo(0.0)      # Foo* foo = new Foo(0.0)
vect = FooVector()  # std::vector<Foo> vect
vect.append(foo)    # vect.push_back(*foo)
footwo = vect[0]    # Foo* footwo = &vect[0]
>>> import example
>>> spam = example.Spam(5)
>>> spams = example.SpamVector()
>>> spams.append(spam)
>>> assert(spams[0].val == 5)
>>> spam.val = 21
>>> assert(spams[0].val == 21)
>>> example.modify_spams(spams)
>>> assert(spam.val == 42)
>>> spams.append(spam)
>>> spam.val = 100
>>> assert(spams[1].val == 100)
>>> assert(spams[0].val == 42) # The container does not provide indirection.