繁体   English   中英

当 C function 返回动态数组时,Python ctypes 行为异常

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM