
On Wed, Feb 27, 2013 at 5:57 PM, Eli Bendersky <eliben@gmail.com> wrote:
I read the cffi docs once again and went through some of the examples. I want to divide this to two topics.
One is what you call the "ABI" level. IMHO, it's hands down superior to ctypes. Your readdir demo demonstrates this very nicely. I would definitely want to see this in the stdlib as an alternative way to interface to C shared objects & DLLs.
Two is what you call the "API" level, which is where my opinion becomes mixed. Some things just don't feel right to me:
1. Tying in a C compiler into the flow of a program. I'm not sure whether we have precedents for it in the stdlib. Does this work on Windows where libraries and DLLs are usually built with MSVC?
Yes. Precedent in the stdlib is really the C API. All the same rules apply (including build and ship a dll).
So would you say that the main use of the API level is provide an alternative for writing C API code to interface to C libraries. IOW, it's in competition with Swig?
the general goal is to provide alternative for writing C API by hand (so SWIG, ctypes, cython, whatever).
2. Using a function called "verify" to create stuff. This may sound like a naming bikeshed, but it's not. It ties in to the question - why is this needed?
We welcome a better opinion of name (indeed verify is not that great). This elevates ABI to API so either invokes the C compiler or reads stuff from the cache.
Can you elaborate on what "elevates ABI to API" means here?
3. The partial type specifications in C with ellipsis. What is the point? You have the C declarations somewhere anyhow, so why introduce this? The "ABI level" boasts having just C and Python to write, but those partial ellipsis-ridden declarations are hardly C.
No, you don't. Some libraries contain macros for example (like OpenSSL) where you just can't use ABI because it makes no sense. It's less common on windows where binary compatibility is important, however looking on linux, multiple stdlib declaration would use ellipsis in the man page.
It would be useful to find an actual example and discuss it concretely.
#define Py_INCREF(x) (x -> refcnt++) the API here is Py_INCREF, which is a macro and does not exist in the DLL. copy-pasting the implementation is not using the API, it's hoping that stuff won't change in the future (and say makes it not working when PyPy implements Py_INCREF as a function). Some POSIX things are macros in one version of glibc and functions in other and there is no change in API so your code will silently stop working.
I can't seem to find one right now, but it's something like:
struct X { int public_field; ... }
which is impossible to do correctly with ctypes without exposing some sort of platform dependency that might change without warning.
Another usages are #define SQLITE_OK ... which you don't know at the time of writing (people assume those won't change and the do change).
Do you mean that the value of SQLITE_OK changed over time (now it's 0, but used to be different?)
If so, then in a realistic use case, how would the API level help solve this?
Eli
no the API is SQLITE_OK. The actual numeric value of 0 is *not* part of the API. it might be 0 it might be not, you never know. In cffi you write: #define SQLITE_OK ... and let the compiler figure out. in ctypes you just hardcode 0. I ended up once with a scary mess of ifs because BSD Linux and OS X were declaring the same numeric constants with different values.