使用Python ctypes从共享库获取浮点数缓冲区到Python字符串

4

我正在尝试使用Python ctypes从共享库中调用这两个C函数:

bool decompress_rgb(unsigned char *data, long dataLen, int scale)
float* getRgbBuffer()
第一个函数已经正常工作了。我可以通过在共享库中添加一些调试代码并检查输入来确定。
问题在于取数据。RGB缓冲区是指向浮点数的指针(显然),这个指针在应用程序的生命周期内保持不变。因此,每当我想解压缩图像时,我都会调用decompress_rgb,然后需要查看由getRgbBuffer指向的位置上有什么值。我知道缓冲区的大小为(720 * 288 * sizeof(float)),所以我猜这个大小需要在某个地方发挥作用。
没有c_float_p类型,所以我想尝试这个:
getRgbBuffer.restype = c_char_p

然后我执行:
ptr = getRgbBuffer()
print "ptr is ", ptr

这只是输出:

ptr = 3078746120

我猜这是实际地址而不是内容,但即使我成功解除指针引用并获取内容,它也只是第一个字符。
如何将整个缓冲区的内容传输到Python字符串中?
编辑:必须更改:
getRgbBuffer.restype = c_char_p

为了

getRgbBuffer.restype = c_void_p

但是BastardSaint的答案最终起作用了。
2个回答

4

没有完全测试,但我认为大致是这样的:

buffer_size = 720 * 288 * ctypes.sizeof(ctypes.c_float)
rgb_buffer = ctypes.create_string_buffer(buffer_size) 
ctypes.memmove(rgb_buffer, getRgbBuffer(), buffer_size)

关键是ctypes.memmove()函数。根据ctypes文档

memmove(dst, src, count)
与标准C memmove库函数相同:将src中的count字节复制到dst中。dstsrc必须是可以转换为指针的整数或ctypes实例。

运行上面的片段后,rgb_buffer.value将返回直到第一个'\0'的内容。要将所有字节作为python字符串获取,可以对整个内容进行切片:buffer_contents = rgb_buffer[:]


谢谢你的建议。我肯定离成功更近了。目前,getRgbBuffer()指针似乎与C函数返回的指针不匹配。我会继续努力,并在我成功时(如果我成功的话)回来标记你的答案为正确的。 - chrism1
如果我将“getRgbBuffer.restype = c_char_p”更改为“getRgbBuffer.restype = c_void_p”,那么我将从getRgbBuffer()中获得正确的地址。不幸的是,“print rgb_buffer.value”没有输出任何内容。 :( - chrism1
现在它可以工作了。首先,我需要将restype设置为c_void_p,并且要查看数据,我必须执行“for a in rgb_buffer:print a”。正如我所说,“print rgb_buffer.value”由于某种原因没有输出任何内容。如果您可以针对这两个问题进行调整,我会将其标记为正确答案。再次感谢。 - chrism1
print rgb_buffer.value 打印内容到第一个 null 字符为止:
import ctypes b = ctypes.create_string_buffer(10) b.value = 'a\0b' b.value 'a' b[:] 'a\x00b\x00\x00\x00\x00\x00\x00\x00' 可能是因为这个原因吧?
不管怎样,现在很高兴它能工作了 :)
- Steef
啊,我的缓冲区可能以空值作为RGB数据的起始值。现在我已经从我的C图像解码器中得到了图片。非常令人满意,谢谢。 - chrism1

2

我已经有一段时间没有使用ctypes了,也没有方便测试返回“double *”的东西,但如果你需要一个c_float_p:

c_float_p = ctypes.POINTER(ctypes.c_float)

阅读BastardSaint的回答,您只是想要原始数据,但我不确定您是否将其作为解决没有c_float_p的问题的变通方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接