如何在Cython中继承C++基类并向继承方法传递self
解决Cython包装C++ Worker/Factory框架的两个问题
你现有C++ Worker/Factory代码如下:
namespace worker { class Worker { public: virtual Worker(); virtual void doWork() = 0; }; class Factory { public: void addWorker(std::unique_ptr<Worker> worker) { workers.push_back(std::move(worker)); } void doWork() { for (auto& worker : workers) { worker->doWork(); } } private: std::vector<std::unique_ptr<Worker>> workers; }; }
针对你用Cython包装时遇到的两个问题,解决方案如下:
问题1:继承cppclass时无法访问实例成员
你的代码错误在于cppclass的成员函数未显式声明self参数,Cython要求cppclass的非静态成员函数必须将self作为第一个参数,否则无法访问实例的成员变量。
修正后的WorkerWrapper代码:
cdef extern from "Worker.h" namespace "worker": cdef cppclass cWorker "worker::Worker": void doWork() except + cdef cppclass WorkerWrapper(cWorker): object worker void __cinit__(self, object worker): self.worker = worker # 必须添加self参数才能访问实例的worker成员 void doWork(self): self.worker.doWork()
问题2:make_unique创建实例时报错
std::make_unique在处理Python对象参数时会触发Python object cannot be passed as a varargs parameter错误,原因是Cython无法正确将Python对象传递给模板构造函数的可变参数列表。解决办法是手动构造std::unique_ptr而非直接调用make_unique。
步骤1:在Cython中声明std::unique_ptr
cdef extern from <memory> namespace "std": template <typename T> cppclass unique_ptr "std::unique_ptr<T>": T* release() void reset(T*) T* get() unique_ptr(unique_ptr&&) noexcept explicit unique_ptr(T*) noexcept
步骤2:手动构造WorkerWrapper实例与unique_ptr
# 假设worker_instance是Python端实现的Worker对象 cdef WorkerWrapper* wrapper_ptr = new WorkerWrapper(worker_instance) cdef unique_ptr[cWorker] worker_uptr = unique_ptr[cWorker](wrapper_ptr) # 传递给Factory的addWorker方法 factory.addWorker(std::move(worker_uptr))
额外注意:避免Python对象悬空引用
为防止Python实现的Worker对象在C++ wrapper生命周期内被提前回收,需要在wrapper的构造/析构中管理引用计数:
cdef cppclass WorkerWrapper(cWorker): object worker void __cinit__(self, object worker): self.worker = worker Py_INCREF(worker) # 增加引用计数 void __dealloc__(self): Py_DECREF(self.worker) # 释放引用计数 void doWork(self): self.worker.doWork()
内容的提问来源于stack exchange,提问作者gruszczy
相关产品推荐
相关产品推荐

