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
错误是意外的,因为这正是教程提供的代码。欢迎任何帮助!提前致谢
规格:
- 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 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
将错误消息更改为“列表必须包含 字节 字符串”也会有所帮助
我正在学习 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
错误是意外的,因为这正是教程提供的代码。欢迎任何帮助!提前致谢
规格:
- 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 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
将错误消息更改为“列表必须包含 字节 字符串”也会有所帮助