【问题标题】:SWIG Converting Python list to a char ** example failsSWIG 将 Python 列表转换为 char ** 示例失败
【发布时间】:2021-10-29 08:23:43
【问题描述】:

我正在关注 SWIG 教程,我目前在以下部分:“32.9.1 Converting Python list to a char **”。有问题的示例在我的机器上返回了 malloc 错误:

import example  
example.print_args(["a","bc","dc"])

python(57911,0x10bd32e00) malloc: 对象 0x7f7ee0406b90 的 *** 错误: 被释放的指针未被分配 python(57911,0x10bd32e00) malloc: *** 在 malloc_error_break 中设置断点进行调试 157911 中止python 157911 中止python

该错误是意外的,因为这正是教程提供的代码。欢迎任何帮助!提前致谢

规格:

  • MacOS 大苏尔
  • Python 3.8
  • C++17

这是我的 setup.py(整个 archive 用于重现性):

#!/usr/bin/env python

"""
setup.py file for SWIG example
"""

from distutils.core import setup, Extension
import os
import sys
import glob

# gather up all the source files
srcFiles = ['example.i']
includeDirs = []

srcDir = os.path.abspath('src')
for root, dirnames, filenames in os.walk(srcDir):
    for dirname in dirnames:
        absPath = os.path.join(root, dirname)
        globStr = "%s/*.c*" % absPath
        files = glob.glob(globStr)
        includeDirs.append(absPath)
        srcFiles += files

extra_args = ['-stdlib=libc++', '-mmacosx-version-min=10.7', '-std=c++17', '-fno-rtti']
os.environ["CC"] = 'clang++'
#
example_module = Extension('_example',
                           srcFiles,  # + ['example.cpp'], # ['example_wrap.cxx', 'example.cpp'],
                           include_dirs=includeDirs,
                           swig_opts=['-c++'],
                           extra_compile_args=extra_args,
                           )

setup(name='example',
      version='0.1',
      author="SWIG Docs",
      description="""Simple swig example from docs""",
      ext_modules=[example_module],
      py_modules=["example"],
      )

【问题讨论】:

    标签: python c++ swig swig-typemap


    【解决方案1】:

    示例代码适用于 Python 2,但有一个错误以及 Python 3 的语法更改。char** 必须传递字节字符串,这是 Python 2 中使用 "string" 语法时的默认设置,但是需要一个领先的b,例如b"string" 在 Python 3 中。

    这行得通:

    import example  
    example.print_args([b"a",b"bc",b"dc"])
    

    崩溃是由于错误调用free 两次,如果发现不正确的参数类型。对示例进行以下更改:

          if (PyString_Check(o)) {
            $1[i] = PyString_AsString(PyList_GetItem($input, i));
          } else {
            //free($1); // REMOVE THIS FREE
            PyErr_SetString(PyExc_TypeError, "list must contain strings");
            SWIG_fail;
    

    SWIG_fail; 最终调用freearg 类型映射,它第二次调用 free。通过此更改,如果传递不正确的参数(例如非列表或 Unicode 字符串而不是字节字符串),您应该会看到以下内容:

    >>> import argv
    >>> argv.print_args(1)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\argv.py", line 66, in print_args
        return _argv.print_args(argv)
    TypeError: not a list
    >>> argv.print_args(['abc','def'])
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\argv.py", line 66, in print_args
        return _argv.print_args(argv)
    TypeError: list must contain strings
    >>> argv.print_args([b'abc',b'def'])
    argv[0] = abc
    argv[1] = def
    2
    

    将错误消息更改为“列表必须包含 byte 字符串”也会有所帮助?

    【讨论】:

    • 谢谢马克。那解决了它。您介意我使用您的回复来建议对文档进行更新吗?我认为 SWIG 维护者会对此感到满意。
    • @Guillaume 继续。可能有很多示例具有 Python 2/3 的差异,但双释放的错误绝对是要修复的。
    猜你喜欢
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 2015-09-02
    • 1970-01-01
    相关资源
    最近更新 更多