Segfault при попытке вызвать функцию Python из C - PullRequest
1 голос
/ 23 февраля 2011

Итак, я хочу вызвать функцию обратного вызова Python из C.

В какой-то момент функция отправляется на C и упаковывается в кортеж, подобный этому

PyObject *userData = Py_BuildValue("Oi",py_callback,some_number);

Где-то в этой области, я тоже Py_INCREF(py_callback).
Позже в программе я хочу вызвать эту функцию

PyObject *py_callback;
int some_number;
PyArg_ParseTuple((PyObject*)userData,"Oi",&py_callback,&some_number); // returns true
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callback,
                                                   /* ... */
                                                   NULL);

и последний вызов вызывает ошибку сегментации. У вас есть идея, почему она так поступила?

Ответы [ 2 ]

5 голосов
/ 23 февраля 2011

При получении странного поведения из API-интерфейса Python C всегда стоит дважды проверить, правильно ли вы управляете состоянием глобальной блокировки интерпретатора (также называемой «GIL»): http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock

1 голос
/ 28 февраля 2011

Я не уверен, почему все говорят о GIL здесь. Вы выпускаете это где-нибудь? Я заметил несколько возможных проблем, которые я перечислю ниже. Это смешано с предложениями.

Я заметил, что вы не увеличиваете счетчик ссылок на userData. Почему бы и нет? Вы храните это не так ли? Почему вы хотите хранить его в кортеже? Почему бы просто не сохранить две переменные (для обратного вызова и данных), а затем увеличить их счетчики ссылок, чтобы у вас была ссылка?

Прежде всего, проверьте возвращаемые значения всех ваших функций, чтобы увидеть, являются ли они NULL. Это позволит вам убедиться, что вы действительно работаете правильно. Также, вероятно, будет хорошей идеей использовать PyObject_Print для печати интересующих вас объектов во всех точках кода, чтобы убедиться, что все идет так, как вы ожидаете.

Из вашего комментария о том, где происходит segfault, я предполагаю, что вы передаете неправильное количество параметров в функцию обратного вызова, когда вызываете ее с помощью PyObject_CallFunctionObjArgs. Вы можете проверить это дважды? Может быть, покажите нам определение вашей функции обратного вызова и затем проверьте вызов снова.

Другая возможная проблема, которую я вижу, заключается в том, что из именования py_some_number звучит так, как будто вы ожидаете целочисленный объект Python. Это не вариант. После PyArg_ParseTuple он будет содержать целое число.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...