3 ms·
What does “talking” C mean? It means getting descriptions of an interface’s types and functions in the form of a C header and somehow: matching the layouts
by eterps 4y ago
What does “talking” C mean? It means getting descriptions of an interface’s types and functions in the form of a C header and somehow:
matching the layouts of those types
doing some stuff with linkers to resolve the function’s symbols as pointers
calling those functions with the appropriate ABI (like putting args in the right registers)
Well we’ve got a few problems here:
You can’t actually write a C parser.
C doesn’t actually have an ABI. Or even defined type layouts.
That we have this situation today still surprises me. I mean I know how we ended up here, but it is so unfortunate and has a huge cost.
- klipt 4y agoC is basically portable* assembly which is why it got so popular. * but see the whole linked article for where portability breaks down.
- fargle 4y agoIt's portable assembler in the language and (mostly) semantics, but not system interfacing. Meaning you can just create functions, loops, assign variables, create expressions etc. in a common syntax that spans a wide variety of CPU architectures. You don't have to know the names of registers and what they are used for, whether you have a register-memory machine or or a load/store machine. If you had to write really assembler programs across multiple machines, you'd appreciate how much above assembly C really is for remarkably low performance cost. I agree with you - I think that's a major part of the popularity - it was not the first systems language, nor high(er)-level language. It was the first that was widely portable, widely applicable (vs. FORTRAN), and equal or better performance than native assembly.
- cryptonector 4y agoWe've always had this situation, but when C was the only real systems programming language around we didn't notice it so much. FFIs were always painful, like JNI, and we accepted it. This situation is much more noticeable now that we have Rust, Go, etc. all trying to be completely detached from the C run-time. And it's not just those. Even languages like Java and Python that do use the C run-time, they all want to have nice and easy FFIs nowadays, but it's still hard to do it safely and elegantly.
- eterps 4y agoDoes anyone know an example of how lowlevel language interop could have been? Without incurring a huge perfomance loss? I imagine a cross language module concept with an accommodating module object file format would be ideal?
- adgjlsfhk1 4y agoall you need for an FFI spec is a calling convention and standard type names.
- eterps 4y agoHmm, did you assume that describing the calling convention and standard type 'names' should be in a separately provided plain text file like it is today?
- cryptonector 4y agoAnd sizes. And layouts.
- pencilguin 4y agoThe place where your language needs to interoperate with the outside world is in OS calls. The modern way to interact with an OS is to stick a request on a ring buffer and get back a request ID, and (eventually) check the response ring for that ID to show up. Like in io_uring. If your language is powerful enough, its OS library can encode that directly (without first marshalling arguments onto a stack that they must then be copied from) for minimal overhead. You might also have an FFI thing so you can call out to libcurl, libzstd and libsqlite. (Do any others matter?) Again, if your language is expressive enough, you can avoid building up an argument list the usual way that must then be reorganized for what the foreign library wants.