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

如何在Cython中创建变长数组指针数组并传递给Python?

在Cython中创建指向不同长度数组的指针数组并返回给Python的解决方案

完全可行,但你的代码里用cpython array模块存储指针的方式存在问题,这就是编译报错Buffers with pointer types not yet supported的核心原因——Python的array模块仅支持存储基本数值类型(如int、float),无法存储指针类型。

原代码的关键错误

  • 错误1:arr.array[unsigned int *]这种定义不被支持,array模块没有存储指针的能力。
  • 错误2:获取数组指针的方式错误,Message1[0]是数组的第一个元素值,而非底层指针,正确的方式是使用Message1.data获取数组的C语言底层指针。

方案1:直接返回Python列表(最简单,推荐)

不需要手动维护C指针数组,直接将各个array对象放入Python列表返回,Python端可直接通过索引访问子数组,完全满足需求。

修改后的代码:

# cython: language_level=3
from cpython cimport array as arr

def mainFunc():
    array_list = ArrayOfPointersGenerator("path")
    print(array_list[0][1])  # 输出12
    print(array_list[1][2])  # 输出23
    return 0

def ArrayOfPointersGenerator(path):
    cdef arr.array[unsigned int] Message1, Message2

    Message1 = arr.clone(arr.array('I'), 2, False)
    Message1[0] = 11
    Message1[1] = 12

    Message2 = arr.clone(arr.array('I'), 3, False)
    Message2[0] = 21
    Message2[1] = 22
    Message2[2] = 23

    # 直接返回包含子数组的Python列表
    return [Message1, Message2]

该方案无需处理内存管理,Python端可像操作普通列表和数组一样使用,简洁高效。


方案2:自定义Cython类封装C指针数组(适用于性能敏感场景)

如果确实需要在C层面维护指针数组,可封装成自定义Cython类,手动管理内存避免泄漏,同时保证Python端可正常访问。

代码示例:

# cython: language_level=3
from cpython cimport array as arr
from libc.stdlib cimport malloc, free

cdef class PointerArray:
    cdef unsigned int** ptr_array
    cdef int length
    cdef list arrays  # 保存原始array对象,防止被Python GC回收导致指针悬空

    def __cinit__(self, int length):
        self.length = length
        # 分配C指针数组的内存
        self.ptr_array = <unsigned int**>malloc(length * sizeof(unsigned int*))
        self.arrays = []

    def __dealloc__(self):
        # 对象销毁时释放C层面的内存
        if self.ptr_array is not NULL:
            free(self.ptr_array)

    def add_array(self, arr.array[unsigned int] arr_obj):
        # 保存原始数组,避免GC回收
        self.arrays.append(arr_obj)
        # 记录数组的底层指针
        self.ptr_array[len(self.arrays)-1] = arr_obj.data

    def __getitem__(self, int idx):
        if idx < 0 or idx >= self.length:
            raise IndexError("索引超出范围")
        # 返回原始数组对象,方便Python访问
        return self.arrays[idx]

def mainFunc():
    pa = ArrayOfPointersGenerator("path")
    print(pa[0][1])  # 输出12
    print(pa[1][2])  # 输出23
    return 0

def ArrayOfPointersGenerator(path):
    cdef arr.array[unsigned int] Message1, Message2
    cdef PointerArray pa = PointerArray(2)

    Message1 = arr.clone(arr.array('I'), 2, False)
    Message1[0] = 11
    Message1[1] = 12

    Message2 = arr.clone(arr.array('I'), 3, False)
    Message2[0] = 21
    Message2[1] = 22
    Message2[2] = 23

    pa.add_array(Message1)
    pa.add_array(Message2)

    return pa

这里通过arrays列表保存原始数组对象,防止Python垃圾回收器销毁它们导致C指针失效;__dealloc__方法负责在自定义类对象被销毁时释放C层面分配的内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:48:28