Python 3.7 和 excess_args 的 SWIG 问题

SWIG issues with Python 3.7 and excess_args

我有一些扩展模块的 C++ 代码,我刚刚从 Python2.7.11 使用较旧的 SWIG 升级到 python3.7.1 使用 SWIG 3.0.12。我遇到了类似于 https://bugs.python.org/issue34495 的问题,只是 Py_None 而不是 nullptrSWIG_Python_NewShadowInstance 中生成的代码调用 tp_new,第二个和第三个参数为 Py_None

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 调用,argskwds 都指向 Py_None

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

然后用 argskwds

调用 excess_args
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 上窒息。

有谁知道如何解决这个问题?

经过更多研究,我在 SWIGs GitHub 页面上找到了 this issue。显然问题已经解决,但没有发布修复的新版本。

更新

显然不需要更新。我用 github 的当前版本替换了 LIb\python\pyrun.swg。那解决了我的问题。万一有人觉得风险太大,可以只修补 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);
      ...
    }
    ...
}

或者只用固定版本替换整个函数。