Обертывание структуры ctypes в классе python вызывает ошибки памяти - PullRequest
1 голос
/ 02 августа 2020

Я пытаюсь сделать функциональность библиотеки C доступной в python с помощью ctypes. Хотя у меня уже есть значительный прогресс, мне нужно подвергнуть сомнению свой подход из-за некоторых проблем с памятью.

Я попытался максимально упростить код, пока я все еще могу воспроизвести проблему. Учитывая следующие определения в библиотеке C:

struct _vector {
  double *v;
  uint dim;
  void *owner;
};

_vector* new_pointer_vector(double* src, uint dim); //uint is just a typedef for unsigned
void print_vector(const _vector* v);

, я могу просто использовать это в python следующим образом:

import ctypes


class CStructVector(ctypes.Structure):
    _fields_ = [
        ('v', ctypes.POINTER(ctypes.c_double)),
        ('dim', ctypes.c_uint),
        ('owner', ctypes.c_void_p)
    ]


lib = ctypes.CDLL('../mylib.so')
new_pointer_vector = lib.new_pointer_vector
new_pointer_vector.restype = ctypes.POINTER(CStructVector)
new_pointer_vector.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_uint]
print_vector = lib.print_vector
print_vector.restype = None
print_vector.argtypes = [ctypes.POINTER(CStructVector)]

Теперь я могу делать следующее в python для создания экземпляра вектора на основе списка, который работает, как ожидалось:

x = [1.0, 2.0, 3.0, 5.0]
cx = (ctypes.c_double * len(x))(*x)
v = new_pointer_vector(cx, len(x))
print_vector(v)
# Output: (1.0000e+00 2.0000e+00 3.0000e+00 5.0000e+00)

Цель моего проекта - скрыть большую часть материала ctypes, чтобы пользователю было как можно проще. Дальнейшее, кажется, беспорядочно с памятью каким-то образом, я не понимаю, как вы можете видеть на выходе. сложные программы работали, как ожидалось, в python. Я надеюсь на любые подсказки о том, как я могу продолжить анализ этой проблемы и, надеюсь, исправить ее.
На случай, если это может быть предложение: использование специального атрибута _as_parameter_ в моем классе Vector вместо cptr, чтобы я мог передать self методу print_vector(), не помогает.

Если у вас есть идеи о том, как достичь той же цели (три строки в нерабочем примере) другим способом, я тоже рад их услышать.

Заранее спасибо за любые ответы.

1 Ответ

1 голос
/ 02 августа 2020

Судя по комментариям, решение заключалось в назначении clst в качестве атрибута в методе __init__ класса Vector:

    def __init__(self, lst):
        self.clst = (ctypes.c_double * len(lst))(*lst)
        self.cptr = new_pointer_vector(self.clst, len(lst))

Оставление его как локальной переменной означало, что Python может собирать мусор после завершения выполнения метода __init__. Очевидно, это вызывало проблемы.

...