3 ms·
> That said, C is not a great glue language: - Zero terminated strings are only used in C so every other language needs to do a copy to pass a string to C, even
by throwawaylinux 5y ago
> That said, C is not a great glue language: - Zero terminated strings are only used in C so every other language needs to do a copy to pass a string to C, even C++ (for string_view at least).
I don't think that's what he's talking about. No matter what glue you had, you need to pass NUL terminated strings to C code that uses NUL terminated strings.
The glue interface does not require any such thing though.
> A lack of fat pointers means that buffers need to pass their pointer and length separately, which is awkward, or use a custom struct which other languages will know nothing about.
Again passing things between two languages will always necessitate that. One language might have a different fat pointer implementation than another.
And the nice thing about glue code is that it can be easily automatically generated calling wrappers so "awkward" does not come into it - you change one language's data types into another's.
> - It has no standardized error handling mechanism to help with writing automatic wrappers on the other language endpoints. - It has no modules or namespacing.
I don't see how this matters for the interface glue. You can define the error handling with it how you like. You put it in your language's namespaces and modules.
- sirwhinesalot 5y agoYour comment is assuming that language A knows about language B. That's one case, but not the usual one. Rather, languages like Rust/Zig/C++ and even C# and Java let you expose a C API such that other languages can understand the shared library as if it was written originally in C, because C is the only thing every other language talks. By necessity this involves using standard types available in C otherwise the other languages have nothing to go on, they'd just have a bunch of opaque types and no way to create them. If C had better builtin constructs, these "extern C" APIs could be much better semantically, such that automatically generating wrappers to this C API would result in safer, more efficient, and more ergonomic code in the host language.
- throwawaylinux 5y ago> Your comment is assuming that language A knows about language B. That's one case, but not the usual one. > Rather, languages like Rust/Zig/C++ and even C# and Java let you expose a C API such that other languages can understand the shared library as if it was written originally in C, because C is the only thing every other language talks. The C interface glue is not the problem here. You can write the library with a completely different language and using fat pointers, and simply adjust the calling convention at the C interface, and it can be called by a different language that uses fat pointers and everything can use fat pointers. The actual problem is you can't just say that your interface glue is going to have all these wonderful features and that therefore everything will magically work and use them. > By necessity this involves using standard types available in C otherwise the other languages have nothing to go on, they'd just have a bunch of opaque types and no way to create them. Using C interface glue does not require you to even write a line of C code let alone C types if your compiler knew how to call the APIs. > If C had better builtin constructs, these "extern C" APIs could be much better semantically, such that automatically generating wrappers to this C API would result in safer, more efficient, and more ergonomic code in the host language. Again there's no reason your language can not wrap those and expose your desired higher level semantics or features to your code on the other side of the wrapper layer.
- sirwhinesalot 5y agoI'm sorry, maybe I'm not making myself clear and we're talking in circles. Yes the C interface is the problem. Lets say I'm developing an API in Rust that I want everyone to be able to use. I wrap this API in some C functions. I use fat pointers (slices), strings with length, etc. all custom struct types. I choose to signal errors in some my_err* parameter. Then someone developing in Java wants to use my library. If they use an automatic wrapper generator (which knows nothing of my API), all the semantic information on slices, strings and errors is lost. They need to make an additional wrapper on top of the stuff the automatic wrapper generator did. If C had better builtin types, the slices exposed by the "extern C" API in Rust would just be standard C slices. The strings just standard C strings, the errors just standard C errors. The semantic information would be preserved at the C level, and therefore the automatic wrapper generator could add code to automatically translate slices, strings and errors into the appropriate types in the host language. You seem entirely focused on the fact that the C ABI can be used to implement stuff like COM or SWIG for language interoperability. True, but not really relevant.
- throwawaylinux 5y agoSince you seem to have vastly the scope of your complaint down to "it doesn't generate all wrapper code automatically for all features", I'll take that as you conceding that the interface does not prevent these features from being implemented across it. Great. And if that's the biggest remaining problem with it, it would be possible to address by augment the interface glue with some extra metadata in a C comment or something nice and simple to describes higher level constructs without the base being tied to or require some specific implementation of them. Just write up a spec and we're done.
- sirwhinesalot 5y agoI agree with you, you can certainly do it, but whatever you do is not the standard that every language talks, because that standard is C :). I can add all the metadata comments I want to my C header saying that the int I return from foo() is an error code, but I'm not going to get Java, C#, Haskell, COBOL, and so on to agree on that new metadata, specially not when each of them would probably come up their own solution. That C became a standard glue that everyone agrees on was a miracle. I can't think of many other standards that pulled that off. It's not happening again. Hence any improvement to C, and C specifically, benefits everyone. Adding extra crap outside the standard does not accomplish the same purpose. I've actually thought of defining such a thing before, but I'd just be reimplementing SWIG, and of course the problem with SWIG is that they have to make all the infrastructure to support the different languages, it isn't the language developers themselves developing the interface (pinvoke, jni, etc.)
- smorgusofborg 5y ago> Your comment is assuming that language A knows about language B. That's one case, but not the usual one. You are free to expose an API where strings are not null terminated, etc. Anyone in any language is going to have to work their data into the API you provide so if it is alternatively complicated to make an intermediary language happy that's not really helping.
- sirwhinesalot 5y agoYou can, but then you cannot automatically generate a wrapper that can convert language B strings to language A strings disguised as an opaque type C, because there is no way for the wrapper generator to know it is a string type, unless you wrote the wrapper generator yourself for your API specifically.
- seiferteric 5y agoThis brings up a vague idea I have had. Redis is sort of a data structure server that can be used across languages. Could we not have an opensource data structure and algorithm library? Where languages, instead of implementing their core types and algorithms in their own library, instead add them (or reuse existing) ones to this library. Then your language becomes just a mapping of your languages semantics over these existing structures & functions.
- sirwhinesalot 5y agoUnfortunately this doesn't work for managed or interpreted languages with their own runtimes, where you want the types to run on their VM. An example would be JIT-compiled C# data structures, no way to implement those on top of a shared library since specific instantiations have to be produced and compiled at runtime. Such a data structure and algorithm library as a springboard would be still be incredibly useful, but then you wonder why it's not called "the C standard library" :)
- seiferteric 5y agoI wonder though, I know a lot of tricks for performance are used, such as in python API, judicious use of inlining, putting some common functions in headers files etc. Depending on how far down the rabbit hole you want to go, could this library not also include code generation functionality for JIT's? Or even at compile time, is there anything stopping a library from generating code that could be included in your VM runtime as just an opaque function that can be called?
- flohofwoe 5y ago> If C had better builtin constructs... Such annotations exist in specific compilers (e.g. clang has things like _Nullable and _Nonnull), they are just not part of the standard (unfortunately). But those annotations are visible in Clang's ast-dump, so they can be used to create more correct language bindings.
- sirwhinesalot 5y agoYes, I'd love it if they got standardized. Having them implemented in a C compiler already helps quite a bit for more "standardized" adoption over some ad-hoc approach. I certainly don't want C to be getting exceptions or templates or other heavyweight constructs, just some QOL stuff that allows for more semantic information to be shared.