1

I have some code C++ code for an extension module that I just upgraded from Python2.7.11 with an older SWIG to python3.7.1 with SWIG 3.0.12. I am experiencing an issue similar to https://bugs.python.org/issue34495, only its Py_None and not nullptr. The generated code in SWIG_Python_NewShadowInstance calls tp_new with Py_None for the 2nd and 3rd argument.

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

which leads to a object_new call with both args and kwds pointing to Py_None

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

and then calls excess_args with args and kwds

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

where PyTuple_GET_SIZE(args) chokes on the Py_None.

Does anyone know how to work around this problem?

Thomas
  • 4,980
  • 2
  • 15
  • 30

1 Answers1

1

After some more research I found this issue on SWIGs GitHub page. Apparently the problem has been fixed but no new version with the fix released.

Udpate

Apparently an update is not necessary. I replaced the LIb\python\pyrun.swg with the current version from github. That solved my problems. In case someone finds that too risky, one can just patch the problematic code section in SWIG_Python_NewShadowInstance, replacing

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

with this

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

or just replace the whole function with the fixed version.

Thomas
  • 4,980
  • 2
  • 15
  • 30