【问题标题】:creating a data type for wrapping structures with ctypes使用 ctypes 创建用于包装结构的数据类型
【发布时间】:2021-01-14 18:25:19
【问题描述】:

所以我正在学习ctypes,我的情况类似于以下:

我有一个共享库,其中包含实现双精度矩阵和复数矩阵的结构。我想用ctypes 包装这两个结构。我知道我可以创建两个类来包装每个结构,但我想知道是否有一种直接的方法可以通过指定数据类型来用一个类包装两个结构。

例如,也许我的库libmatrix.so 有以下源文件:

// matrix.c

struct complex {
    double re;
    double im;
};

struct Matrix {
    int nrow;
    int ncol;
    double *data
};

struct CMatrix {
    int nrow;
    int ncol;
    complex *data
};

typedef struct complex complex;
typedef struct Matrix Matrix;
typedef struct CMatrix CMatrix;

包装我的complex 结构后,可能是这样的:

class complex(Structure):
    __fields__ = [("re", c_double), ("im", c_double)]

在 python 中,我想创建一个类 Matrix,它可以让我执行以下操作:

# create 2 x 3 matrix of doubles 
m = Matrix(2, 3, dtype=c_double)

# create 2 x 3 matrix of complex numbers (structure that I made)
n = Matrix(2, 3, dtype=complex)

我知道 numpy 有这样的东西,我尝试查阅源代码,但不知所措。这种类型的东西有名称或有参考吗?任何方向都将不胜感激。

【问题讨论】:

    标签: python c ctypes


    【解决方案1】:

    这是一个粗略的例子。 Python 中的一切都是对象,因此可以直接传递数据类型并用于分配数组。一些覆盖使矩阵更易于操作和显示。

    from ctypes import *
    from pprint import pformat
    
    class Complex(Structure):
    
        _fields_ = (('re',c_double),
                    ('im',c_double))
    
        def __repr__(self):
            return f'Complex({self.re}{self.im:+}j)'
    
        def __str__(self):
            return f'{self.re}{self.im:+}j'
    
    class Matrix(Structure):
    
        _fields_ = (('nrow',c_int),
                    ('ncol',c_int),
                    ('data',c_void_p))
    
        def __init__(self,row,col,dtype):
            self.nrow = row
            self.ncol = col
            self._data = (dtype * col * row)() # internal instance of allocated array
            self.data = cast(byref(self._data),c_void_p) # generic pointer to array
    
        # forward to the array instance
        def __getitem__(self,key):
            return self._data.__getitem__(key)
    
        # forward to the array instance
        def __setitem__(self,key,value):
            return self._data.__setitem__(key,value)
    
        def __repr__(self):
            return pformat([r[:] for r in self._data])
    
    mc = Matrix(2,3,Complex)
    md = Matrix(3,2,c_double)
    mc[1][2] = Complex(1.1,-2.2)
    md[2][1] = 1.5
    print(mc)
    print(md)
    

    输出:

    [[Complex(0.0+0.0j), Complex(0.0+0.0j), Complex(0.0+0.0j)],
     [Complex(0.0+0.0j), Complex(0.0+0.0j), Complex(1.1-2.2j)]]
    [[0.0, 0.0], [0.0, 0.0], [0.0, 1.5]]
    

    【讨论】:

    • 嘿,谢谢你的回答,我花了一天的大部分时间来消化它,它真的很有帮助。它还帮助我了解了更多关于 c 编程的知识:)
    猜你喜欢
    • 2022-10-25
    • 2021-04-30
    • 1970-01-01
    • 2022-07-27
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 2015-11-30
    相关资源
    最近更新 更多