Managing void pointers in cffi

820 views
Skip to first unread message

Davide Del Vento

unread,
Aug 7, 2013, 7:29:59 PM8/7/13
to pytho...@googlegroups.com
Folks,

first thanks for cffi, it seems a great project (I've used SWIG before). I'm just a newbie of cffi, so pardon if my question is silly. I've looked at the documentation and at this forum and I've not found an answer. The most similar one is https://groups.google.com/forum/#!msg/python-cffi/E2QmmxyYPgA/MVXsV9k4A7UJ but it does not cover my use case.

I need to call a C function (from a library) whose argument is pointer to void. It's the C way of saying that the argument is "anything", and the library decided to do this way to implement just one function with the type specified as argument instead of a bunch of different identical functions The way I'd do this in C would be just create my stuff, possibly cast it (optional) and pass it to the func. Note that the func may change its value and I want to have that value back.

In C, is something like

#include <mylib.h>
double v = 2.34;
err = func(v, 1,DOUBLE_PRECISION);
// do something with err
printf("%d", v);

As you can see, the type and size must be passed explicitly (but that's not a big deal).

I'm trying to do this (in pypy, FWIW) with cffi as follows

ffi.cdef("""
typedef int datatype
int func(void*, int, datatype);
#define DOUBLE_PRECISION ...;
""")
C = ffi.verify("""#include <mylib.h>""")

value = ffi.new("double *", 2.34);
v = ffi.cast("void *", value)
err = C.func(v, 1, C.DOUBLE_PRECISION)

Up to this point it seems to work. However, I cannot use the returned value (which is why I called func in the first place). If I do

print v[0]

I get

TypeError: cannot return a cdata 'void'

If I cast the appropriate datatype with:

value = ffi.cast("double *", v)
print value[0]

I get Segmentation fault.

What am I doing wrong or better what's the recommended way to use a C function with void * arguments?

Thanks
Davide

Alex Gaynor

unread,
Aug 7, 2013, 7:32:29 PM8/7/13
to pytho...@googlegroups.com
I'm not sure I understand your example, such code doesn't compile for me in C:

Alexanders-MacBook-Pro:tmp alex_gaynor$ cat x.c
void g(void *, int);


void f(double x) {
    g(x, 0);
}
Alexanders-MacBook-Pro:tmp alex_gaynor$ gcc x.c
x.c: In function ‘f’:
x.c:5: error: incompatible type for argument 1 of ‘g’


I think once you have C code which really works it's easier to convert it to CFFI :)

Alex



Davide

--
-- python-cffi: To unsubscribe from this group, send email to python-cffi...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/python-cffi?hl=en
---
You received this message because you are subscribed to the Google Groups "python-cffi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-cffi...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
"I disapprove of what you say, but I will defend to the death your right to say it." -- Evelyn Beatrice Hall (summarizing Voltaire)
"The people's good is the highest law." -- Cicero
GPG Key fingerprint: 125F 5C67 DFE9 4084

Davide Del Vento

unread,
Aug 7, 2013, 7:37:25 PM8/7/13
to pytho...@googlegroups.com
You're right I forgot an ampersand. Too much python these days :-)
My C code is:


#include <mylib.h>
double v = 2.34;
err = func(&v, 1,DOUBLE_PRECISION);

// do something with err
printf("%d", v);

(and adding a & to your example makes it compile - but of course not link since you did not specify anything for g).

Alex Gaynor

unread,
Aug 7, 2013, 7:39:19 PM8/7/13
to pytho...@googlegroups.com
This appears to work ok for me:

>>> import cffi
>>> ffi = cffi.FFI()
>>> ffi.cdef("""
... void f(void *);
... """)
>>> ffi.verify("""
... void f(void *x) {
... }
... """)
clang: warning: argument unused during compilation: '-mno-fused-madd'
<cffi.vengine_cpy.FFILibrary object at 0x10c4a1f90>
>>> lib = _
>>> x = ffi.new("double *", 3.2)
>>> lib.f(x)
>>> x[0]
3.2


Alex

Davide Del Vento

unread,
Aug 9, 2013, 6:09:08 PM8/9/13
to pytho...@googlegroups.com
You are right. This works perfectly. Let me add a slightly better example for the sake of the readers of this conversation at a later time. I suggest (and hereby grant permission and copyright) to use this example in the docs:


import cffi
ffi = cffi.FFI()
ffi.cdef("""void f(void *);""")

lib=ffi.verify("""void f(void *x) { *(double *)x = 3.3;  }""")


x = ffi.new("double *", 3.2)
print x[0]
lib.f(x)
print x[0]

Thanks a bunch!
Dav

Armin Rigo

unread,
Aug 10, 2013, 3:10:42 AM8/10/13
to pytho...@googlegroups.com
Hi Davide,

On Sat, Aug 10, 2013 at 12:09 AM, Davide Del Vento
<davide.d...@gmail.com> wrote:
> You are right. This works perfectly.

Do you understand what was wrong with your original example?
Referring to your first e-mail here: it looks a lot like the final example
you posted, but with additionally explicit casts from "double *" to "void
*" and back to "double *". But this works for me too. Why doesn't it
work for you? Can you post a complete example that fails with a
segfault?


A bientôt,

Armin.
Reply all
Reply to author
Forward
0 new messages