> 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?

> 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.
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?