Обратный вызов Cython, вызывающий повреждение памяти / segfaults - PullRequest
1 голос
/ 25 мая 2011

Я связываю Python с библиотекой C ++, используя Cython.Мне нужна функция обратного вызова, которую может вызвать код c ++.Мне также нужно передать ссылку на конкретный объект Python этой функции.Это все очень ясно из демонстрации обратного вызова.

Однако я получаю различные ошибки при вызове обратного вызова из потока c ++ (pthread):

  1. Передача указателя на функцию и класса / объекта (как void *) в c ++
  2. Сохранить указатели в c ++
  3. Начать новый поток (pthread), запустив цикл
    1. Вызвать функцию, используя указатель сохраненной функции, и передать обратно классуказатель (void *)
  4. В python: приведение void * обратно к классу / объекту
  5. Вызов метода вышеуказанного класса / объекта (ошибка)

Шаги 2 и 3 выполняются на языке c ++.

В основном это ошибки сегментации, но иногда я получаю жалобы на некоторые вызовы Python низкого уровня.

У меня точно такой же код, где ясоздать поток в Python и вызвать обратный вызов напрямую.Это работает хорошо.Таким образом, сам обратный вызов работает.

Мне нужен отдельный поток, работающий на c ++, так как этот поток взаимодействует с оборудованием, а иногда вызывает мой обратный вызов.

Я также трижды проверил всеуказатели, которые передаются вокруг.Они указывают на допустимые местоположения.

Я подозреваю, что есть некоторые проблемы при использовании классов Cython из потока c ++ ..?

Я использую Python 2.6.6 в Ubuntu.

Итак, мой вопрос: могу ли я манипулировать объектами Python из не-Python-потока?Если нет, есть ли способ сделать поток Python-совместимым?(pthread)

Это минимальный обратный вызов, который уже вызывает проблемы при вызове из потока c ++:

cdef int CheckCollision(float* Angles, void* user_data):
    self = <CollisionDetector>user_data
    return self.__sizeof__() # <====== Error

1 Ответ

1 голос
/ 26 мая 2011
  1. Нет, вы не должны манипулировать объектами Python без получения GIL. Вы должны использовать PyGILState_Ensure() + PyGILState_Release() (см. Документацию PyGILState_Ensure )

  2. Вы можете гарантировать, что ваш объект не будет удален python, если вы явно берете ссылку, и освобождаете ее, когда вы больше не используете ее с Py_INCREF() и Py_DECREF(). Если вы передадите обратный вызов в ваш c ++, и если у вас больше нет ссылки, возможно, ваш объект python освобожден и произойдет сбой (см. Документацию Py_INCREF ).

Отказ от ответственности: я не говорю, что это ваша проблема, просто даю вам советы, чтобы отследить ошибку:)

...