#python #c #ctypes
#python #c #ctypes
Вопрос:
Итак, я изучаю, 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 есть что-то подобное, я попытался обратиться к исходному коду, но я был перегружен. Есть ли имя для такого типа вещей или есть ссылка? Любое направление было бы действительно оценено.
Ответ №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]]
Комментарии:
1. Эй, спасибо за ваш ответ, я потратил большую часть дня на его переваривание, и это было действительно полезно. Это также помогло мне узнать больше о программировании на c 🙂