SWIG 将 Python 列表转换为 char ** 示例失败

SWIG Converting Python list to a char ** example fails

我正在学习 SWIG 教程,目前我在“32.9.1 Converting Python list to a char **”部分。有问题的例子 returns 我机器上的 malloc 错误:

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

python(57911,0x10bd32e00) malloc: *** error for object 0x7f7ee0406b90: pointer being freed was not allocated python(57911,0x10bd32e00) malloc: *** set a breakpoint in malloc_error_break to debug 1 57911 abort python 1 57911 abort python

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

规格:

这是我的 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 2,但有一个错误以及 Python 3 的语法更改。char** 必须传递字节字符串,它们是使用 "string" 语法时默认为 Python 2,但需要前导 b,例如b"string" 在 Python 3.

这个有效:

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

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

      if (PyString_Check(o)) {
        [i] = PyString_AsString(PyList_GetItem($input, i));
      } else {
        //free(); // 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

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