vector_indexing_suite返回的奇怪对象 [英] weird object returned by vector_indexing_suite

查看:107
本文介绍了vector_indexing_suite返回的奇怪对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个

std::vector<const T*>

我从c ++函数返回的

:

that I return from a c++ function:

getallTs()

我用以下方法公开了T类:

I have exposed the T class with:

class_<T,T*> 

和向量是这样的:

class_<std::vector<const T*> >("TsList")
  .def(vector_indexing_suite<std::vector<const T*>,true>())
;

NoProxy参数是什么意思?

What does the NoProxy argument mean?

我这样公开函数:

  def("getallTs", getallTs,
      return_value_policy<return_by_value>{});

我观察到一种奇怪的行为.

I observe a weird behaviour.

当我从python调用时

When I call from python

tlist = getallTs()

我得到一个TsList对象.

I get a TsList object.

len(tlist)

有效.

tlist[<anycorrectindex>].<someattribute> 

也可以.

但是,如果我只是

print(tlist[0])

print(tlist[100])

python打印

object T at <address>

此地址对于tlist中的所有T都是相同的.

This address is the same for all the Ts in tlist.

此外,我无法使用python for循环遍历Tlist.

Also, I cannot iterate over Tlist with a python for loop.

for t in tlist: 

不起作用.

任何想法我将向量和函数暴露给python的方式有什么问题吗?

Any ideas what is wrong with the way I am exposing the vector and the function to python?

我了解每个包装c ++ T的python对象都包含一个指向T的原始指针. 这些T实例在整个过程中都存在于全局表中.

I understand the python objects that each wrap a c++ T hold a raw pointer to T. These T instances exist throughout the process in a global table.

c ++函数重新调整了指向这些实例的指针的向量. indexing_suite对这些有何作用?

The c++ function retunrns a vector of pointers to those instances. What does indexing_suite do with those?

谢谢

推荐答案

按索引访问元素时,索引套件默认提供元素的代理,以此为Python用户经常使用的可变类型提供参考语义.期望与收藏:

When accessing elements by index, the indexing suite defaults to providing a proxy to the element, as a means to provide reference semantics for mutable types that Python users will often expect with collections:

val = c[i]
c[i].m()            # Mutates state, equivalent to `val.m()`
assert(val == c[i]) # Have same state.
val.m()
assert(val == c[i]) # Have same state.

在上面的示例中,val是了解容器元素的代理对象.当NoProxytrue时,索引时将获得值语义,从而在每次索引访问时产生一个副本.

In the above example, val is a proxy object that is aware of the container element. When NoProxy is true, one gets value semantics when indexing, resulting in a copy on each index access.

val = c[i]  # val is a copy.
c[i].m()    # Modify a copy of c[i].
assert(val == c[i]) # These have the same state because c[i] returns a new copy.
val.m()
assert(val != c[i]) # These do not have the same state.

当不使用代理时,仅当在对元素的引用上调用(例如在迭代过程中)时,元素的突变才会持续存在:

When proxies are not used, the mutations to the elements will only persists when invoked on a reference to the element, such as during iteration:

for val in c:
    val.m() # modification observed in c[#]


当调用print(c[i])时,将创建一个临时代理对象并将其传递给print,并且该代理对象的生存期在从print()返回时结束.因此,可以重新使用临时代理对象使用的存储器和标识.这可能导致元素看起来具有相同的标识:


When invoking print(c[i]), a temporary proxy object is created and passed to print, and the lifetime of the proxy object ends upon returning from print(). Hence, the memory and identification used by the temporary proxy object may be re-used. This can result in elements appearing to have the same identification:

id0 = id(c[0]) # id of the temporary proxy
id1 = id(c[1]) # id of another temporary proxy
assert(id0 ?? id1) # Non-deterministic if these will be the same.
assert(c[0] is not c[1]) # Guaranteed to not be the same.

另一方面,在代理的生存期内,同一元素的其他代理将具有相同的标识,而不同元素的代理将具有不同的标识:

On the other hand, during the lifetime of a proxy, other proxies to the same element will have identical identification, and proxies to different elements will have different identification:

c0 = c[0]   # proxy to element 0.
c0_2 = c[0] # another proxy to element 0.
c1 = c[1]   # proxy to element 1
assert(c0 is c0_2)
assert(c0 is c[0])
assert(c0 is not c1)


T被暴露为由T*持有的情况下,如果没有const T*到Python对象的Python转换,则std::vector<const T*>上的迭代将在Python中失败.将类T公开为由T*持有,将为T*(而不是const T*)注册自动到Python和从Python的转换.在Python中遍历集合时,将返回对元素的引用,导致无法从const T*构造Python对象.另一方面,当通过索引访问元素时,生成的Python对象是代理或副本,可以使用现有的转换器.要解决此问题,请考虑以下任一方法:


In the situation where T has been exposed as being held by T*, iteration over std::vector<const T*> will fail in Python if there is no to-Python conversion for const T* to a Python object. Exposing class T as being held by T* registers automatic to-Python and from-Python conversions for T*, not const T*. When iterating over the collection in Python, references to elements are returned, resulting in a Python object failing to be constructed from a const T*. On the other hand, when accessing elements via index, the resulting Python object is either a proxy or a copy, which can use the existing converters. To resolve this, consider either:

  • std::vector<>的元素类型与T的保留类型相同
  • 明确注册const T*至Python转换器
  • having std::vector<>'s element type be the same as T's held type
  • explicitly registering a const T* to-Python converter

这篇关于vector_indexing_suite返回的奇怪对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆