我有一个关于 python 返回对象值的问题。 使用
pybind11
与 python3 接口 C++ 函数
使用Dask做分布式计算
以下是 progeam 片段。
// ------------ 开始 pyCmd1.cpp --------------
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
namespace py = pybind11;
class dbPrep {
public:
dbPrep() : m_type(-9999) {};
void setType(const int t) { m_type = t;}
int getType() const { return m_type; }
//
private:
int m_type;
};
PYBIND11_MODULE(pyCmd1, m) {
m.doc() = "pybind11 for dask data passing"; // Optional module docstring
//
py::class_<dbPrep>(m, "dbPrep")
.def(py::init<>())
//.def(py::init<int>())
.def("set_type", &dbPrep::setType)
.def("get_type", &dbPrep::getType)
// see https://github.com/pybind/pybind11/blob/master/docs/upgrade.rst
// "New API for defining custom constructors and pickling functions"
//
.def(py::pickle(
[](const dbPrep &self) { // __getstate__
return py::make_tuple();
},
[](py::tuple t) { // __setstate__, note: no `self` argument
return new dbPrep();
// or: return std::make_unique<Foo>(...); // return by holder
// or: return Foo(...); // return by value (move constructor)
}
)
)
;
}
// ----- 结束 pyCmd1.cpp ------------------
//-------- 开始 pyCmd1.py -----------------
import dask
from dask.distributed import Client
import pyCmd1
def init_db():
db = pyCmd1.dbPrep()
db.set_type(100)
print("@ init_db, type = ", db.get_type())
return db
`if __name__ == "__main__":
# Create a Dask client with 2 workers
client = Client(n_workers=2)
db_init = client.submit(init_db)
r1 = client.gather(db_init)
print("> db_init type = ", r1.get_type())
#
client.close()
// --- 结束 pyCmd1.py ---------
输出: @init_db,类型=100
db_init 类型 = -9999
在 python 函数 init_db() 中创建一个“dbPrep”对象,并将成员数据“type”设置为 100。 然后返回对象。
问题: 为什么返回的对象db_init的值'type'不是100而是初始值-9999? `
要调试此问题,您应该在尝试进行 pickle 往返时检查对象的行为:
db = pyCmd1.dbPrep()
db.set_type(100)
print(pickle.loads(pickle.dumps(db))
在我看来,您的
__setstate__
正在创建一个新的dbPrep,但没有初始化任何状态。