我有一个非常大的std::vector
从C ++函数返回,我们称之为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 ++源代码。
答案 0 :(得分:1)
编辑:@DavidW发出警告后,我意识到我误解了您的问题。下面的答案只是让您直接从cython使用模板化的from socket import AF_INET, SOCK_STREAM, socket, gethostname
from tkinter import *
from tkinter import ttk
IP = gethostname() # or "127.0.0.1"
PORT = 1337
root = Tk()
root.title("")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
root.bind('<Return>', connectionFunc)
def connectionFunc(*args):
# this way you dont have to close the socket.
with socket(AF_INET, SOCK_STREAM) as s:
s.listen()
s.bind((IP, PORT))
conn, addr = s.accept()
with conn:
print(f"connection from: {addr}")
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
root.mainloop()
,而无需为每种移动类型(例如,在问题中为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))))
和Cython 0.29.12和Python 3.7.3编译):
cythonize -3 -i test.pyx
请注意,Cython当前正在执行C ++对象的默认初始化,但是此帮助函数允许在初始化后调用移动分配。
编辑:我将此代码段打包为cymove。