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 包装器? [复制]

SWIG:你能否使用 SWIG 专门使用 C++ 头文件使 C++ 在 Python 中可用?

在 win32 服务 (C++) 中生成 casablanca http_listener 的问题