我想知道我是否可以得到一些帮助。对于上下文,我使用一些 C++ 库生成一些大(想想数百 Mb)对象,我想通过网络从服务器发送到客户端。
在服务器上,我有以下内容:
PyObject* CKKSwrapper::SerializePrivateKey() {
std::string s;
std::ostringstream os(s);
Serial::Serialize(m_keys.publicKey, os, SerType::BINARY);
auto msg = os.str();
return PyBytes_FromString(&msg[0]);
}
这给了我一些 Python 对象。然后我通过 python 套接字将其直接发送到客户端。我正在阅读它
def _safe_recv_abstract(socket: Socket, deserializer_func):
expected_length = _get_obj_size(socket)
running_length = 0
running_msg = bytearray()
while running_length < expected_length:
msg = socket.recv(expected_length)
if msg:
running_msg = cppwrapper.Accumulator(running_msg, bytearray(msg))
running_length += len(msg)
socket.send(_add_header_to_payload(b"ACK"))
logger.debug("_safe_recv_unenc_obj: Received all data")
if optional_pycrypto_deserialize_func:
return deserializer_func(running_msg)
return running_msg
两件事:
- 累加器(来自上面的
cppwrapper.Accumulator()
)看起来像
PyObject* CKKSwrapper::Accumulator(PyObject a, PyObject b){
return PyByteArray_Concat(&a, &b);
}
deserializer_func
调用一个底层 C++ 函数,看起来像
void CKKSwrapper::DeserializeX(
const boost::python::list &pyvals) {
auto msg= pythonListToCppVectorBytes(pyvals);
LPPrivateKey<DCRTPoly> sk;
std::istringstream is(string(msg.begin(), msg.end()));
Serial::Deserialize(sk, is, SerType::BINARY);
this->m_keys.secretKey = sk;
}
我遇到了以下错误:
Boost.Python.ArgumentError: Python argument types in
CKKSwrapper.Accumulator(bytearray, bytearray)
did not match C++ signature:
Accumulator(pycrypto::CKKSwrapper {lvalue}, _object*, _object*)
我完全理解它在说什么,类型是错误的,但我不确定为什么。来自docs
PyObject* PyByteArray_Concat(PyObject *a, PyObject *b)
Return value: New reference.
Concat **bytearrays** a and b and return a new bytearray with the result.
如果我理解正确,我正在传递字节数组,但它说它正在等待对象?
我尝试这样做的原因是,当我使用字节数组或列表进行累加时,即
while running_length < expected_length:
msg = socket.recv(expected_length)
if msg:
running_msg = cppwrapper.Accumulator(running_msg, bytearray(msg))
running_length += len(msg)
内存使用和运行时间爆炸
最佳答案
简单错误的部分答案:
PyObject* CKKSwrapper::Accumulator(PyObject a, PyObject b)
应该是
PyObject* CKKSwrapper::Accumulator(PyObject* a, PyObject* b)
PyObject
从不按值传递,总是按指针传递。在实践中,所有有用的 Python 对象都像这样:
struct Something{
PyObject ob_base;
Useful data;
};
这本质上是 C++ 继承的 C 版本。通过按值传递,您将失去除 ob_base
之外的所有内容,就像按值传递 C++ 派生类作为其基数一样。
关于python bytearray 到 C++ 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66466372/