gpt4 book ai didi

c++11 - Cython:避免通过 std::move 复制不起作用

转载 作者:行者123 更新时间:2023-12-02 01:38:47 26 4
gpt4 key购买 nike

问题

我有一个从 C++ 函数返回的非常大的 std::vector ,我们称之为 getVector()

现在我想将该函数包装在 Cython 中:

cdef extern from "XY.h":
cdef cppclass _XY:
vector[double] getVector() except +

cdef class XY:
cdef _XY _this

...

def getVector():
return self._this.getVector()

因为我想避免复制这个大向量,所以我想使用 std::move。像这样:
cdef extern from "<utility>" namespace "std":
vector[double] move(vector[double]) # Cython has no function templates

这以下列方式修改 Cython 源代码:
def getVector():
return move(self._this.getVector())

问题

上面的想法行不通。 Cython(至少)产生 1 个载体副本。
我认为这是因为无法从向量中移动,因为这已经是 C++ 中实际 std::vector 类的 Cython 包装器。

是否有另一种方法可以避免任何副本?我想避免从 C++ 方法返回一个指针。

可能有一种方法是通过定义一个 C++ 包装器类来存储向量,然后在 Cython 中移动这个类,但我想知道是否有一种不(或很少)修改 C++ 源代码的方法。

最佳答案

编辑: 在@DavidW 发出警告后,我意识到我误解了您的问题。下面的答案只是让您直接使用来自 cython 的模板化 move,而无需为每种移动类型(例如,您在问题中为 std::vector<double> 声明的类型)进行显式声明。

您可以使用此辅助函数来包装 std::move 调用:

# distutils: language = c++

cdef extern from * namespace "polyfill":
"""
namespace polyfill {

template <typename T>
inline typename std::remove_reference<T>::type&& move(T& t) {
return std::move(t);
}

template <typename T>
inline typename std::remove_reference<T>::type&& move(T&& t) {
return std::move(t);
}

} // namespace polyfill
"""
cdef T move[T](T)

用法示例:
# distutils: language = c++

cdef extern from *:
"""
#include <iostream>

#define PRINT() std::cout << __PRETTY_FUNCTION__ << std::endl

struct Test {
Test() { PRINT(); }
~Test() { PRINT(); }
Test(const Test&) { PRINT(); }
Test(Test&&) { PRINT(); }
Test& operator=(const Test&) { PRINT(); return *this; }
Test& operator=(Test&&) { PRINT(); return *this; }
};

void f(const Test&) { PRINT(); }
void f(Test&&) { PRINT(); }
"""

cdef cppclass Test:
pass

cdef void f(Test)

from move cimport move

cdef Test t1, t2

print("# t1 = t2")
t1 = t2

print("# t1 = move(t2)")
t1 = move(t2)

print("# f(t1)")
f(t1)

print("# f(move(t1))")
f(move(t1))

print("# f(move(move(t1)))")
f(move(move(t1)))

print("# f(move(move(move(t1))))")
f(move(move(move(t1))))

输出(使用 cythonize -3 -i test.pyx 和 Cython 0.29.12 和 Python 3.7.3 编译):
$ python3 -c "import test"
Test::Test()
Test::Test()
# t1 = t2
Test& Test::operator=(const Test&)
# t1 = move(t2)
Test& Test::operator=(Test&&)
# f(t1)
void f(const Test&)
# f(move(t1))
void f(Test&&)
# f(move(move(t1)))
void f(Test&&)
# f(move(move(move(t1))))
void f(Test&&)
Test::~Test()
Test::~Test()

请注意,C++ 对象仍然默认初始化,因为这是 Cython 当前所做的,但此辅助函数允许在初始化后调用移动分配。

编辑: 我将此代码段打包为 cymove

关于c++11 - Cython:避免通过 std::move 复制不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29571780/

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