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
而不是 nullptr
。 SWIG_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
调用,args
和 kwds
都指向 Py_None
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
if (excess_args(args, kwds)) {
然后用 args
和 kwds
调用 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);
...
}
...
}
或者只用固定版本替换整个函数。
我有一些扩展模块的 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
。
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)) {
然后用 args
和 kwds
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);
...
}
...
}
或者只用固定版本替换整个函数。