gpt4 book ai didi

c++ - Cython 为 libcpp.list 赋值

转载 作者:行者123 更新时间:2023-11-30 01:34:10 28 4
gpt4 key购买 nike

有没有办法在 Cython 赋值之前进行取消引用,例如在 C++ 列表中就地赋值?

Cython 文档 ( here ) 说你应该使用 dereference(foo) 来生成像 *(foo) 这样的 C++ 代码,但是这个语法不能用于赋值(例如 *(foo) = *(foo) + 1

下面我展示了一个我无法使用 Cython 解引用函数实现的赋值示例(在 inplace_normalize 函数中)。

from libcpp.list cimport list as cpplist
from cython.operator import dereference as deref, preincrement as inc

cpdef cpplist[double] normalize(cpplist[double] l):
cdef double norm
cdef cpplist[double] l2

for v in l:
norm += v

for v in l:
l2.push_back(v/norm)

return l2

# inplace version of normalize
cpdef void inplace_normalize(cpplist[double] l):
cdef double norm
for v in l:
norm += v

cdef cpplist[double].iterator it = l.begin()
while it != l.end():
# deref(it) = deref(it)/norm #== *it = *it / norm
print(deref(it)/norm)
inc(it)

如果我尝试使用 deref(it) = deref(it)/norm,我会收到错误消息 Cannot assign to or delete this。使用 Cython 在 libcpp.list 中就地分配值的解决方案是什么?

最佳答案

对于指针,您可以使用 pt[0] 而不是 (*pt) 因为指针和数组在 C 中密切相关。然而,同样的技巧并不适用非常适合 C++ 迭代器。因此,我们需要做的是获取项目的地址。粗略的(未经测试的)大纲是:

cdef void inplace_normalize(cpplist[double]& l):
cdef double norm
cdef double* address
for v in l:
norm += v

cdef cpplist[double].iterator it = l.begin()
while it != l.end():
address = &deref(it)
address[0] = address[0]/norm #== *it = *it / norm
print(deref(it)/norm)
inc(it)

几个要点:

  • C++ list 很少是您想要的 - 您可能需要 C++ vector,它更接近 Python list 并且通常效率更高。

  • 我已将函数从 cpdef 更改为 cdef。如果您尝试从 Python 调用它,它会首先将 Python 可迭代对象复制到 C++ 列表中,然后它会规范化该列表的内容,但您所做的更改永远不会传播回可迭代对象。从 Python 调用它是没有意义的(因为你不能在 Python 中直接拥有 cpplist 对象)所以最好阻止它。

  • 我已将其从按值传递更改为按引用传递。修改列表的本地拷贝没有意义。

关于c++ - Cython 为 libcpp.list 赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56837803/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com