Mam trochę kodu C++ dla modułu rozszerzenia, który właśnie zaktualizowałem z Python2.7.11 ze starszym SWIG do python3.7.1 ze SWIG 3.0.12. Mam problem podobny do https://bugs.python.org/issue34495, tylko jego Py_None, a nie nullptr. Wygenerowany kod w SWIG_Python_NewShadowInstance wywołuje tp_new z Py_None dla drugiego i trzeciego argumentu.

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); 

Co prowadzi do połączenia object_new z args i kwds wskazującymi na Py_None

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

A następnie dzwoni excess_args z args i kwds

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

Gdzie PyTuple_GET_SIZE(args) dławi się na Py_None.

Czy ktoś wie, jak obejść ten problem?

1
Thomas 1 listopad 2018, 00:18

1 odpowiedź

Najlepsza odpowiedź

Po kilku dalszych badaniach znalazłem ten problem na stronie SWIGs GitHub. Najwyraźniej problem został naprawiony, ale nie ma nowej wersji z wydaną poprawką.

UDPATE

Najwyraźniej aktualizacja nie jest konieczna. Zastąpiłem LIb\python\pyrun.swg aktualną wersją z github . To rozwiązało moje problemy. Jeśli ktoś uzna to za zbyt ryzykowne, może po prostu załatać problematyczną sekcję kodu w SWIG_Python_NewShadowInstance, zastępując

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);
    ...
}

Z tym

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);
      ...
    }
    ...
}

Lub po prostu zamień całą funkcję na wersję stałą.

1
Thomas 3 listopad 2018, 12:49