Проблемы SWIG с Python 3.7 и extra_args - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть некоторый код C ++ для модуля расширения, который я только что обновил с Python2.7.11 с более старой версией SWIG до python3.7.1 с SWIG 3.0.12. Я испытываю проблему, похожую на https://bugs.python.org/issue34495, только ее Py_None, а не nullptr. Сгенерированный код в SWIG_Python_NewShadowInstance вызывает tp_new с Py_None для 2-го и 3-го аргумента.

SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
{
    ...
    #if PY_VERSION_HEX >= 0x03000000
    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); 

, что приводит к вызову object_new, в котором args и kwds указывают на Py_None

object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    if (excess_args(args, kwds)) {

, а затем звонит excess_args с args и kwds

excess_args(PyObject *args, PyObject *kwds)
{
    return PyTuple_GET_SIZE(args) ||
        (kwds && PyDict_Check(kwds) && PyDict_GET_SIZE(kwds));

, где PyTuple_GET_SIZE(args) дроссели на Py_None.

Кто-нибудь знает, как обойти эту проблему?

1 Ответ

0 голосов
/ 01 ноября 2018

После еще одного исследования я обнаружил эту проблему на странице GITHub SWIG. Очевидно, проблема была исправлена, но новая версия с исправлением не выпущена.

Udpate

Видимо, обновление не требуется. Я заменил LIb\python\pyrun.swg на текущую версию github . Это решило мои проблемы. Если кто-то считает это слишком рискованным, можно просто пропатчить проблемный код в SWIG_Python_NewShadowInstance, заменив

SWIGRUNTIME PyObject* 
SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
{
     ...
#if PY_VERSION_HEX >= 0x03000000
    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
    ...
}

с этим

SWIGRUNTIME PyObject* 
SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
{
     ...
#if PY_VERSION_HEX >= 0x03000000
    PyObject *empty_args = PyTuple_New(0);
    if (empty_args) {
      inst = ((PyTypeObject *)data->newargs)->tp_new((PyTypeObject *)data->newargs, empty_args, Py_None);
      Py_DECREF(empty_args);
      ...
    }
    ...
}

или просто замените всю функцию фиксированной версией.

...