Retrieving a buffer of integers from a C function

52 views
Skip to first unread message

Gary Pajer

unread,
Jun 10, 2016, 11:35:16 AM6/10/16
to python-cffi
This is similar to my previous problem, but different enough.  

I'm retrieving a 1024 x 1024 image from a camera. Each pixel is a 16 bits.  The software library contains a function to read rows, but it does not include a function to grab the entire frame.
In order to get the entire frame, the function FLIGrabRow() is called repeatedly, and it seems to keep track of where it left off, so subsequent reads read the next line of pixels.

The function FLIGrabRow() loads the values for a row into a buffer.   In C, the way this is done:


    // function declaration
   
long FLIGrabRow(long dev, void* buff, size_t width);

   
long img_rows = 1024;
   
long row_width = 1024;
   
long img_size = img_rows * row_width;
    uint16_t img
[img_size]

   
// (dev is a long that identifies the device)

   
// read data into array
   
for (int row = 0; row < img_rows; row++)
   
{
       
FLIGrabRow( dev, &img[row * (row_width)], row_width);
   
}


As the loop continues, we index farther into the buffer, row by row.


My attempt at reading one line using cffi is

buff_p = ffi.new("uint16_t[1024]")

lib
.FLIGrabRow(dev[0], buff_p, 1024)
x
= ffi.unpack(buff_p, 1024)
print x

dev[0] contains the device address; the syntax here works for other functions in the library.  

The results in a printout of 1024 zeros.    I put this in a loop in an attempt to read several rows in the event the first few rows were indeed zeros, but all the output is zeros.  (The C code works; the buffer in the C application is not filled with zeros.)

Any suggestions?

P.S.  I'm a scientist, not a programmer, so reading the docs is a bit of a struggle.  Armin suggested using ffi.set_source(), but I can't figure out how to make that work.  The docs are pretty quiet on that functionality.  In particular, I can't figure out how to pass parameters into and out of functions defined using ffi.set_source().   It sounds like a great facility, and would probably save us time and effort if I can figure it out.   More generally, I really don't have a good handle on what cffi is doing under the hood, what a cdata object is and how to use it.  Perhaps there are examples somewhere that I haven't found?






Armin Rigo

unread,
Jun 10, 2016, 1:12:22 PM6/10/16
to pytho...@googlegroups.com
Hi,

Your example of using cffi looks fine. I don't know what the problem
is without being able to reproduce the example myself... Maybe check
carefully that you didn't misdeclare some function in cdef()? If
you're using dlopen(), even small differences in the declaration can
lead parameters being wrongly passed. (That's another advantage of
set_source().)

> Armin suggested using ffi.set_source(), but I can't figure out
> how to make that work. The docs are pretty quiet on that functionality.

I'm not sure which pages you have read, but
http://cffi.readthedocs.io/en/latest/overview.html#real-example-api-level-out-of-line
is the introduction for set_source(). Everywhere else the docs attempt
to push forward set_source() in preference to dlopen(). But for some
reason people are still thinking that they should try dlopen() instead
of set_source(). I'm lost about why it is so. Maybe I should
completely remove the overview examples about dlopen(), and only
mention dlopen() in the full reference with a big warning box ("only
use if you know what you're doing, because x y z")?


A bientôt,

Armin.

Gary Pajer

unread,
Jun 10, 2016, 2:29:47 PM6/10/16
to python-cffi, ar...@tunes.org
Should I be using ffi.buffer() instead of ffi.unpack()?

As for set_source() ... my eyes were too focused, and I thought that ffi.set_source() was different than ffibuilder.set_source()   ...

But now here's my "builder":

ffibuilder.set_source(
   
"_grabrow",
   
"""
    long dev = 0;
    long size = 1024;
    uint16_t img[1024];
    long x = FLIGrabRow( dev, img[0], size);
    """
,
    libraries
=["/usr/local/lib/libfli.so"]
)


ffibuilder
.cdef("""

long FLIGrabRow(long dev, void *buff, size_t width);
""")


if __name__ == "__main__":
    ffibuilder
.compile(verbose=True)

but it fails with

_grabrow.c:426:14: warning: implicit declaration of function 'FLIGrabRow' is invalid in C99 [-Wimplicit-function-declaration]

    long x = FLIGrabRow( dev, img[0], size); 

             ^

_grabrow.c:426:14: error: initializer element is not a compile-time constant

    long x = FLIGrabRow( dev, img[0], size); 



Among other things, I'm not seeing how to pass parameters to the function I define in set_source()

 

A bientôt,

Armin.

Armin Rigo

unread,
Jun 11, 2016, 2:44:06 AM6/11/16
to pytho...@googlegroups.com
Hi Gary,

On 10 June 2016 at 20:29, Gary Pajer <gary....@gmail.com> wrote:
> Should I be using ffi.buffer() instead of ffi.unpack()?
>
> As for set_source() ... my eyes were too focused, and I thought that
> ffi.set_source() was different than ffibuilder.set_source() ...
>
> But now here's my "builder":
>
> ffibuilder.set_source(
> "_grabrow",
> """
> long dev = 0;
> long size = 1024;
> uint16_t img[1024];
> long x = FLIGrabRow( dev, img[0], size);
> """,
> libraries=["/usr/local/lib/libfli.so"]
> )

Please read again
http://cffi.readthedocs.io/en/latest/overview.html#real-example-api-level-out-of-line
, the whole section (two pages).


Armin
Reply all
Reply to author
Forward
0 new messages