SWIG 在 Windows 中生成 C++ Python3 包装器导致断言 MSVC 2017
Posted
技术标签:
【中文标题】SWIG 在 Windows 中生成 C++ Python3 包装器导致断言 MSVC 2017【英文标题】:SWIG Generating C++ Python3 wrapper in Windows causes assertion MSVC 2017 【发布时间】:2018-11-14 13:16:31 【问题描述】:使用 SWIG 围绕 C++ 类生成包装器会导致运行时出现奇怪的断言:
Assertion failed!
Program: C:\Python37\python37_d.dll
File: c:\_work\4\s\objects\typeobject.c
Line: 3634
Expression: PyTuple_Check(args)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts
(Press Retry to debug the application - JIT must be enabled)
如果在弹出的对话框中点击忽略,一切似乎都正常。
我创建了一个示例程序来尝试复制问题并遇到了同样的问题:
main.cpp
#include "testwrapper.h"
#pragma push_macro("slots")
#undef slots
#include "Python.h"
#pragma pop_macro("slots")
#include "SwigModules/generated/swig_runtime.h"
PyObject * ConvertToWrapper(SwigInterface * instance)
swig_type_info * pTypeInfo = SWIG_TypeQuery("SwigInterface *");
PyObject* obj = SWIG_NewPointerObj(instance, pTypeInfo, 0); <- issue occurs here
return obj;
TestWrapper * wrapper = new TestWrapper();
void TestSwig()
Py_Initialize();
PyRun_SimpleString("import test_module");
ConvertToWrapper(wrapper);
Py_Finalize();
int main(int argc, char *argv[])
TestSwig();
return 0;
testwrapper.h
#pragma once
#include "swiginterface.h"
class TestWrapper : public SwigInterface
public:
TestWrapper()
virtual ~TestWrapper()
virtual void Test();
;
swiginterface.h
#pragma once
class SwigInterface
public:
virtual ~SwigInterface()
virtual void Test() = 0;
;
test_module.i(swig 接口文件)
%module test_module
%
#include "../swiginterface.h"
%
%include "../SwigInterface.h"
%inline %
SwigInterface * test;
%
setup_function (python)
from distutils.core import setup, Extension
setup(name="test_module",
py_modules=['test_module'],
ext_modules=[Extension("_test_module",
["test_module.i"],
extra_compile_args=["-DSWIG_TYPE_TABLE=test_module"],
swig_opts=["-c++", "-py3"],
)])
出现问题的 swig_runtime.h 中的函数:
SWIGRUNTIME PyObject*
SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
#if (PY_VERSION_HEX >= 0x02020000)
PyObject *inst = 0;
PyObject *newraw = data->newraw;
if (newraw)
inst = PyObject_Call(newraw, data->newargs, NULL);
if (inst)
#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
PyObject **dictptr = _PyObject_GetDictPtr(inst);
if (dictptr != NULL)
PyObject *dict = *dictptr;
if (dict == NULL)
dict = PyDict_New();
*dictptr = dict;
PyDict_SetItem(dict, SWIG_This(), swig_this);
#else
PyObject *key = SWIG_This();
PyObject_SetAttr(inst, key, swig_this);
#endif
else
#if PY_VERSION_HEX >= 0x03000000
inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); //<----- HERE
if (inst)
PyObject_SetAttr(inst, SWIG_This(), swig_this);
Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
#else
PyObject *dict = PyDict_New();
if (dict)
PyDict_SetItem(dict, SWIG_This(), swig_this);
inst = PyInstance_NewRaw(data->newargs, dict);
Py_DECREF(dict);
#endif
return inst;
我已经使用多个版本的 SWIG 进行了尝试,结果都相同。它将模块加载到 C++ 代码和外部 python 解释器中都没有问题。我该如何调试/修复这个问题?
【问题讨论】:
调试失败的调用?我想某处有一些Python?它在哪里? 此时没有python,它用于将指针传递给python,以便它可以在嵌入式解释器中使用。该代码适用于 Linux / Mac 并使用以前版本的 windows。 instance 和 pTypeInfo 指针都可以。最后一个参数是用于标志的,应该设置为 0 在 Windows 上,我#undef _DEBUG
在包含 Python.h
之前明确链接到 Python37 的发布版本。您的错误可能与 python 库的调试/发布链接有关
【参考方案1】:
为了解决这个问题,我需要从 Python3.7 降级到 Python3.6
【讨论】:
【参考方案2】:或升级到具有fix 的 SWIG 4.0。
【讨论】:
以上是关于SWIG 在 Windows 中生成 C++ Python3 包装器导致断言 MSVC 2017的主要内容,如果未能解决你的问题,请参考以下文章
在 Windows 中为 python 编译 SWIG 包装器
如何在 C++ 中生成 UUID,而不使用 boost 库?
如何在 swig 接口文件中集成可以抛出 MyException 的 C++ 函数
如何使用 SWIG 在 C++ API 上生成 C 包装器? [复制]