![](/img/trans.png)
[英]Python ctypes function returns ValueError when C function returns NULL
[英]Python ctypes misbehaves when a C function returns a dynamic array
我正在为 Matlab 的动态库开发 Python 包装类,以读取 Python 中的 Matlab MAT 文件,而我遇到的奇怪行为无法解释我遇到的界面。
C function 签名如下所示:
const mwSize *mxGetDimensions(const mxArray *);
在这里, mwSize
是一个重命名的size_t
,而 mxArray mxArray*
是一个不透明的指针。 此 function 返回 Matlab 数组的“形状”。 返回的指针指向 size_t 数组,该数组内部存储在 mxArray object 中,并且不是null 终止的(其大小通过另一个函数获得)。
要从 Python 调用此 function,我将库设置如下:
libmx = ctypes.cdll.LoadLibrary('libmx.dll')
libmx.mxGetDimensions.restype = ctypes.POINTER(ctypes.c_size_t)
libmx.mxGetDimensions.argtypes = [ctypes.c_void_p]
在VAR
中获得mxArray*
后,我调用:
dims = libmx.mxGetDimensions(VAR)
print(dims[0],dims[1])
VAR
是二维的,形状为(1, 13)
(使用 C 程序验证),但我的 Python 代码在 c_ulonglong 中返回(55834574849 0)
结果始终存储在所有变量的垃圾中测试 MAT 文件。
我究竟做错了什么? 其他使用 VAR 的库调用似乎工作正常,因此 VAR 指向有效的 object。 如上所述,在 C 程序中调用的 mxGetDimensions() 按预期工作。
任何输入将不胜感激! 谢谢
@Neitsa 在 OP 下的评论中解决了我的直接问题,对 libmx.dll 的进一步调查解决了 Python 和 Z0D61F8370CAD1D412F80B84D143E1277 版本之间的剩余差异。
因为 Matlab 的 libmx.dll 可以追溯到很长时间,因为它最初是在 32 位时代编写的,所以 DLL 包含多个版本的函数以实现向后兼容性。 事实证明, const mwSize *mxGetDimensions(const mxArray *);
is the oldest version of the function, and the associated C header file (matrix.h) has the line #define mxGetDimensions mxGetDimensions_800
to override the function with its newest version. 显然,Python 的 ctypes 不会检查 C header 文件; 所以,留给我筛选 header 文件以确定使用哪个版本的 function。
最后,当我将代码POINTER(c_size_t)
为:
libmx = ctypes.cdll.LoadLibrary('libmx.dll')
libmx.mxGetDimensions_800.restype = ctypes.POINTER(ctypes.c_size_t)
libmx.mxGetDimensions_800.argtypes = [ctypes.c_void_p]
dims = libmx.mxGetDimensions_800(VAR)
所以,你有它:如果你要包装一个第 3 方动态/共享库,请彻底研究相关的 header 文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.