You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 02:05:17