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

如何用Cython包装C++的std::shared_ptr与std::vector并简化初始化?

封装TypeToWrap并实现Python风格的初始化与操作

首先明确:TypeToWrap是std::shared_ptr<std::vector<Value>>的别名,要让它在Python里像数组一样便捷使用,需要在Cython里做两层包装——先封装智能指针+vector的组合,再给ClassToWrap做适配。下面是具体实现步骤:

1. 声明C++类型依赖

先在Cython文件中引入C++标准库头文件,声明目标ClassToWrap模板类:

# distutils: language = c++
from libcpp.vector cimport vector
from libcpp.memory cimport shared_ptr

# 引入你的C++类头文件
cdef extern from "your_class_header.h":
    template <typename Value>
    class ClassToWrap:
        # 声明TypeToWrap类型别名
        ctypedef shared_ptr[vector[Value]] TypeToWrap
        # 声明构造函数
        ClassToWrap(TypeToWrap data)

2. 封装TypeToWrap为Python可操作类

写一个模板化的Cython类,把shared_ptr<vector<Value>>包装起来,实现Python序列接口(索引、迭代、长度等),让它支持列表式初始化和赋值:

cdef class WrappedTypeToWrap[Value]:
    cdef shared_ptr[vector[Value]] _inner_ptr

    def __cinit__(self, sequence=None):
        # 初始化智能指针和底层vector
        self._inner_ptr = shared_ptr[vector[Value]].__new__(shared_ptr[vector[Value]])
        self._inner_ptr.reset(new vector[Value]())
        
        # 支持从Python序列(列表/元组)直接初始化
        if sequence is not None:
            for item in sequence:
                self._inner_ptr.get().push_back(Value(item))

    # 实现索引访问
    def __getitem__(self, int idx):
        if idx < 0 or idx >= self._inner_ptr.get().size():
            raise IndexError("Index out of range")
        return self._inner_ptr.get()[idx]

    # 实现索引赋值
    def __setitem__(self, int idx, value):
        if idx < 0 or idx >= self._inner_ptr.get().size():
            raise IndexError("Index out of range")
        self._inner_ptr.get()[idx] = Value(value)

    # 支持Python循环迭代
    def __iter__(self):
        cdef int i
        for i in range(self._inner_ptr.get().size()):
            yield self._inner_ptr.get()[i]

    # 动态添加元素
    def append(self, value):
        self._inner_ptr.get().push_back(Value(value))

    # 获取容器长度
    def __len__(self):
        return self._inner_ptr.get().size()

3. 封装ClassToWrap类

让ClassToWrap的Python包装类接受上面的WrappedTypeToWrap实例,完成与C++类的对接:

cdef class WrappedClassToWrap[Value]:
    cdef ClassToWrap[Value]* _cpp_obj

    def __cinit__(self, WrappedTypeToWrap[Value] data):
        # 传入TypeToWrap类型的智能指针
        self._cpp_obj = new ClassToWrap[Value](data._inner_ptr)

    def __dealloc__(self):
        # 释放C++对象内存
        del self._cpp_obj

4. 实例化具体类型

Cython模板需要实例化为具体类型才能在Python中调用,比如针对int类型:

# 导出int版本的包装类供Python使用
WrappedTypeToWrapInt = WrappedTypeToWrap[int]
WrappedClassToWrapInt = WrappedClassToWrap[int]

Python侧使用示例

现在你可以像操作普通Python列表一样使用封装后的类型:

# 从列表初始化TypeToWrap
data = WrappedTypeToWrapInt([10, 20, 30])

# 循环赋值修改元素
for i in range(len(data)):
    data[i] = data[i] + 5

# 遍历输出结果
for num in data:
    print(num)  # 输出15, 25, 35

# 动态添加元素
data.append(40)
print(data[-1])  # 输出40

# 创建ClassToWrap实例
cpp_obj = WrappedClassToWrapInt(data)

关键注意点

  • 类型转换:基础Python类型(int、float等)可自动转换为C的Value类型;如果是自定义类型,需要额外实现Python到C类型的转换逻辑。
  • 内存管理:shared_ptr会自动管理vector的内存,Cython包装类的__dealloc__负责释放ClassToWrap对象,无需手动干预。
  • 多维数组支持:如果需要多维数组,可将Value替换为vector<InnerValue>,嵌套使用WrappedTypeToWrap即可,比如WrappedTypeToWrap[vector[int]],Python侧用嵌套列表初始化。

内容的提问来源于stack exchange,提问作者Giovanni Barbarani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:00:42