Вы можете вызывать PyImport_Import()
столько раз, сколько захотите, но вы просто продолжите возвращать один и тот же объект модуля. Импорт кэшей Python. Кроме того, вместо создания новой строки Python и утечки ссылки (и, следовательно, объекта), вы должны просто использовать PyImport_ImportModule()
, что занимает const char *
.
PyImport_Import*()
вернуть новую ссылку, однако, вы должны вызвать Py_DECREF()
, когда закончите. Хранение модуля в глобальном порядке не должно быть проблемой, если у вас есть ссылка на него (что вы делаете здесь).
При вызове PyEval_CallObject()
вы не проверяете результат Py_BuildValue()
на наличие ошибок, и вы также не вызываете Py_DECREF()
, когда закончите с ним, поэтому вы пропускаете этот объект как хорошо.
Чтобы преобразовать число с плавающей точкой Python в двойник C, вам, вероятно, следует просто позвонить PyFloat_AsDouble()
, а не копаться с PyArg_Parse()
(и иметь в виду, что нужно проверять исключения)
Вплоть до фактической обработки ошибок: PyErr_ExceptionMatches()
полезен только тогда, когда вы действительно хотите проверить, соответствует ли исключение чему-либо. Если вы хотите узнать, произошло ли исключение, или получить фактический объект исключения, PyErr_Occurred()
- это то, что вы должны вызывать. Возвращает текущее исключение тип (не фактический объект исключения) в качестве заимствованной ссылки или NULL, если ни одно не установлено. Если вы хотите просто напечатать трассировку в stderr, PyErr_Print()
и PyErr_Clear()
- это то, что вы хотите использовать. Для более детальной проверки фактической ошибки в вашем коде PyErr_Fetch()
возвращает вам текущий объект исключения и трассировку, связанную с ним (он получает ту же информацию, что и sys.exc_info()
в коде Python). Все вещи считаются вами редко хочу глубоко вникнуть в обработку исключений в C-коде.