On May 20, 2013, at 8:54 PM, C Anthony Risinger <[email protected]> wrote:

> i know the impl is pretty simple, but i havent had the opportunity to 
> complete yet -- are there other reasons to use cffi over ctypes? my 
> experience with ctypes is not extensive either.

The real reason to prefer it is that ctypes communicates with C code at the ABI 
level, whereas cffi uses the API level.

When you read documentation for a C library, it generally goes like:

you should include <foo.h>
you should call a function that looks like 'int foo_bar(char* baz, qux_t qux)'
you should link against -lfoo

When you use cffi, this is all you need to know.  You act on 'include <foo.h>' 
by putting it in your 'verify' section; you act on 'call a function that looks 
like' by pasting the 'looks like' into your 'cdef' section, and you link 
against -lfoo by passing arguments as if you were building a distutils 
extension with libfoo.so.  So, you do each of these things in a 
previously-accepted, well-documented way.  If you get any of these things 
wrong, you will most likely get a nice, comprehensible C compiler error 
message, that points at some very comprehensible generated C code.  (Of course 
you can screw up regular C programming stuff and induce the library to 
dereference a freed pointer or something and get a segfault, but this is 
actually much harder with cffi than with actual C code, for most of the regular 
reasons that Python code is safer, and also some cffi-specific things about the 
way it handles pointers.)  If you move this code to a system with different 
linker properties or header files, you get exactly the same behavior a C 
programmer would get, with compile errors that indicate you've got the wrong 
version of foo.h or link errors that tell you it can't find libfoo, during the 
build process.

Whereas, with ctypes, you act on 'include <foo.h>' by reading foo.h with a 
magnifying glass, and maybe running 'cpp' over it and running the output.  You 
act on 'call a function that looks like' by putting your debugger hat on and 
inspecting 'foo_bar' to figure out if that's really a function, or a macro that 
just *looks* like a function call that does some other funky thing, or a macro 
that simply re-names a versioned symbol; you need to find the actual symbol 
name in your local copy of the library.  You need to figure out the precise 
memory layout of 'qux' so you can re-describe it.  If you get any of these 
things wrong, you get a segfault, possibly at some random later point in your 
program.  If you move to a system with different linker properties or header 
files, you'd better hope everything matches your development system exactly or 
you've written custom code to detect that platform, because the C compiler 
can't help you and there isn't enough metadata in the C library to tell you 
that your bindings are now wrong.  To make matters worse, you can't really tell 
that anything's broken until your program is running; it will fail late, and in 
weird ways.

Sorry for such a long message, but I recently had the experience of playing 
with cffi to wrap some C code and it was just _great_, whereas my previous 
experiences with ctypes were mediocre to miserable.  If you're going to wrap 
some C code I really recommend giving it a try.  If you're interested, more 
info is available here: <http://cffi.readthedocs.org/en/latest/>

-glyph

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"Pyjs.org Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to