Причина ошибки заключается в следующем: функции расширения Python должны иметь определенный прототип C:
PyObject *func(PyObject *self, PyObject *args)
Слоты методов содержат указатели на функции типа
PyObject *(*)(Pyobject *, PyObject *)
Старый способ был принудительно приводить функцию к этому типу указателя для сохранения в слоте метода.Явное приведение отключит ошибку преобразования void (*)()
в PyObject *(*)(Pyobject *, PyObject *)
.Преобразование допустимо, но нуждается в явном приведении. Если явного преобразования нет, то компилятор C должен выдать диагностическое сообщение .
Ваш код не имеет явного преобразования, поэтому вы должны получить предупреждение для
{"gen_nums", gen_nums, METH_VARARGS, "This is a threading test"},
В любом случае, , если было явное приведение , программабудет по-прежнему правильной программой до тех пор, пока Python не попытается вызвать вашу функцию gen_nums()
, потому что Python сделает так , как если бы ее прототип был
PyObject *gen_nums(PyObject *, PyObject *);
Теперь стандарт C говорит, что хотя до этого момента все было в порядке , с этого момента поведение программы равно undefined , потому что C11 6.3.2.3 :
Указатель на функцию одного типа может быть преобразован в указатель на функцию другого типа и обратно;результат должен сравниваться равным исходному указателю. Если преобразованный указатель используется для вызова функции, тип которой не совместим с указанным типом, поведение не определено.
Ваша функция возвращает void, то есть вообще ничего, но вы спрашиваете "почему он возвращает NULL
только тогда, когда там Sleep()
. Причина -" неопределенное поведение ".
Что касается того, как исправьте это , пожалуйста, прочитайте и поймите Глава 1 из 1. Расширение Python с помощью C или C ++ - там много подробностей, но все, что нужно для исправления этой простой функции, подробнотам. Если вы застряли, пожалуйста, do задайте дополнительные вопросы, но обратитесь к документации в вопросах.
Исправление для в том, что функция должна была бы записать ее как
static PyObject *gen_nums(PyObject *self, PyObject *args) {
int i;
for(i = 0; i < 10; i++) {
printf("Printed from C thread...\n");
Sleep(1000);
}
Py_RETURN_NONE;
}