Question

I'm trying to use python ctypes to use these two C functions from a shared library:

bool decompress_rgb(unsigned char *data, long dataLen, int scale)
float* getRgbBuffer()

The first function is working fine. I can tell by putting some debug code in the shared library and checking the input.

The problem is getting the data out. The RGB buffer is a pointer to a float (obviously) and this pointer stays constant during the life of the application. Therefore whenever I want to decompress an image, I call decompress_rgb and then need to see what's at the location pointed to by getRgbBuffer. I know that the buffer size is (720 * 288 * sizeof(float)) so I guess this has to come into play somewhere.

There's no c_float_p type so I thought I'd try this:

getRgbBuffer.restype = c_char_p

Then I do:

ptr = getRgbBuffer()
print "ptr is ", ptr

which just outputs:

ptr = 3078746120

I'm guessing that's the actual address rather than the content, but even if I was successfully dereferencing the pointer and getting the contents, it would only be the first char.

How can I get the contents of the entire buffer into a python string?

Edit: Had to change:

getRgbBuffer.restype = c_char_p

to

getRgbBuffer.restype = c_void_p

but then BastardSaint's answer worked.

Was it helpful?

Solution

Not fully tested, but I think it's something along this line:

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

Key is the ctypes.memmove() function. From the ctypes documentation:

memmove(dst, src, count)
Same as the standard C memmove library function: copies count bytes from src to dst. dst and src must be integers or ctypes instances that can be converted to pointers.

After the above snippet is run, rgb_buffer.value will return the content up until the first '\0'. To get all bytes as a python string, you can slice the whole thing: buffer_contents = rgb_buffer[:].

OTHER TIPS

It's been a while since I used ctypes and I don't have something which returns a "double *" handy enough to test this out, but if you want a c_float_p:

c_float_p = ctypes.POINTER(ctypes.c_float)

Reading BastardSaint's answer, you just want the raw data, but I wasn't sure if you're doing that as a workaround to not having a c_float_p.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top