python - 从 ctypes 访问大内存缓冲区时的段错误
问题描述
在 Python 中访问内存时出现“分段错误(核心转储)”错误,该内存最初是在共享库中分配的。
返回内存的函数声明为:
extern "C" double *get_sound_data(int desc);
extern "C" long long get_sound_data_size(int desc);
Python代码是:
from ctypes import *
cdll.LoadLibrary("libsomelib.so")
_lib = CDLL("libsomelib.so")
size = _lib.get_sound_data_size(desc)
data = _lib.get_sound_data(desc)
data = cast(data, POINTER(c_double))
arr = []
for i in range(size):
arr.append(data[i])
对于小的缓冲区,比如 10k 个项目,它可以工作,但是当库返回几兆字节时,第一次访问尝试,即 Python 段错误中的 data[0]。
我看过这个页面,它看起来很相似https://bugs.python.org/issue13096
我在 Python 2.7.12 和 3.5.2 中遇到同样的错误,操作系统是 Linux。
解决方案
您不能只是假装默认返回类型很好,并尝试将您得到的无意义结果转换为它应该是的类型。(实际上,Python 可能不应该为此设置默认值,但更改它为时已晚。)默认值是假定 C 函数返回 C int,并且不能保证 C int 的大小与指针; 这些天,它可能不是。
您需要实际设置argtypes
并restype
能够通过ctypes
.
get_sound_data = _lib.get_sound_data
get_sound_data_size = _lib.get_sound_data_size
get_sound_data.argtypes = (ctypes.c_int,)
get_sound_data.restype = ctypes.POINTER(ctypes.c_double)
get_sound_data_size.argtypes = (ctypes.c_int,)
get_sound_data_size.restype = ctypes.c_longlong
# Now use the functions
推荐阅读
- visual-studio - 带 * 的 AssemblyVersion 只生成“0.0”
- angular - 如何为 @Inject(DOCUMENT) 文档创建单元测试:Angular 中的文档
- java - 如何使用 @PathVariable 参数映射 ResponseEntity<> getByName 方法?
- javascript - 为什么这个 for 循环不起作用并且我的变量为零?
- javascript - 客户端与服务器端的视频编码
- vue.js - Vuetify:天:小时:分钟的v-text-field?
- python - PMU RAW文件的IEEE C37.118 python解析器
- javascript - 如何防止 ECMAScript 模块改变全局对象?
- javascript - 使用jquery根据标签html更改单选按钮选中属性
- python - 为什么我不能使用 np.isnan 过滤数据框?