vector_indexing_suite 返回的奇怪对象

weird object returned by vector_indexing_suite

我有一个

std::vector<const T*>

我 return 来自 c++ 函数:

getallTs()

我已经将 T class 暴露为:

class_<T,T*> 

向量像这样:

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

NoProxy 参数是什么意思?

我这样公开函数:

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

我观察到一个奇怪的行为。

当我从 python

打电话时
tlist = getallTs()

我得到一个 TsList 对象。

len(tlist)

有效。

tlist[<anycorrectindex>].<someattribute> 

也有效。

但是,如果我只是

print(tlist[0])

print(tlist[100])

python 打印

object T at <address>

这个地址对于tlist中的所有T都是一样的。

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

for t in tlist: 

不起作用。

知道我将向量和函数公开给 python 的方式有什么问题吗?

我理解 python 每个包装 C++ T 的对象都有一个指向 T 的原始指针。 这些 T 实例在整个过程中以全局 table.

的形式存在

C++ 函数返回指向这些实例的指针向量。 indexing_suite 用这些做什么?

谢谢,

当通过索引访问元素时,索引套件默认为元素提供代理,作为一种为可变类型提供引用语义的方法,Python 用户通常希望使用集合:

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 时,在索引时获取值语义,从而在每次索引访问时生成一个副本。

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.

当不使用代理时,元素的变化只会在对元素的引用被调用时持续存在,例如在迭代期间:

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

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

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.

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

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* 的情况下,如果没有 to-[=,对 std::vector<const T*> 的迭代将在 Python 中失败53=] 将 const T* 转换为 Python 对象。将 class T 公开为由 T* 持有会自动注册到-Python 和从-Python 的转换 T*,而不是 const T*.当遍历 Python 中的集合时,返回对元素的引用,导致无法从 const T* 构造 Python 对象。另一方面,当通过索引访问元素时,生成的 Python 对象是代理或副本,可以使用现有的转换器。要解决此问题,请考虑:

  • std::vector<>的元素类型与T的持有类型相同
  • 显式注册一个 const T* 到-Python 转换器