Rune interaction with C/C++/Rust

1 view
Skip to first unread message

Bill Cox

unread,
May 5, 2023, 4:55:12 PM5/5/23
to Rune language discussion
I think a top priority for Rune should be simple interaction with other popular systems programming languages.  Specifically, I think we should make Rune libraries easy and even fun to use from C, C++, and Rust.  In the other direction, we are limited by the target language.

The C language designers managed to design a systems programming language that is easy to interface to from newer systems programming languages, like C++, and Rust, which all support the C linker.  Rune is also designed to easily interface with C, but at a C library level.  Unfortunately, C++ went down a path that more or less requires the world to use nothing but C++ to use C++ libraries.  Consider C++ try/catch.  The LLVM scheme for handling C++ exceptions is so convoluted and specific to C++ that probably no other language will ever support it.  Carbon will most likely require Google-style StatusOr<T> everywhere to avoid the C++ exception handling system.  That means Carbon may work well for Google's legacy libraries, but most of the rest of the world will not be so lucky.

C++ decided to throw/catch dynamically typed exceptions.  The catch statements don't know what type was thrown, so the compiler builds C++-specific RTTI (run-time type information), which is compiler specific, making it impossible for any two C++ compilers to share libraries, other than g++ and clang++, because clang made it a top priority objective to interoperate with gcc.

In Rune, I think we need to take care to avoid such limitations to interoperability.  In particular, for each language where we support strong interoperability, we should:
  • Have flags to generate code in the target language to call functions compiled into our .so and .a libraries.
  • Ensure things like exceptions are handled cleanly in extern interfaces.
For exceptions, I think  this means we need to restrict what we can throw.  I think Rust errs on the side of too little flexibility: only a single error type can generally be returned, requring SWEs to write more error translation code than I've seen in any other language.  I think we can return errors that:
  • Have an Enum class selection defined in an Enum class that even C can handle.
  • All Enum error classes that a function can throw should be declared automatically in generated interfaces to supported languages.
For example, consider a function that sends out both HTTP requests, and Stubby requests.  The HTTP errors could be (status: HttpStatus, msg: string), and the RPC errors could be (status: StatusCode, msg: string).  To be able to return either, the generated code for C might look like:

enum ErrorCodeType {
  HttpStatus = 1,
  StatusCode = 2,
}
extern ErrorCodeType global_error_code_type;
union ErrorCode {
  http_status;
  status_code;
};
extern union ErrorCode global_error_code;

Then a function returning a value, say a struct Foo, and an error/status code could look like;

// The caller needs to check global_error_code for being non-zero, and handle exceptions.
extern "C" struct Foo GetFoo();

The C code call would look like:

struct Foo foo = GetFoo();
if !global_errror_code) {
  handleException();  // Or possibly goto :handle_error.
}

Rune code trying to be compatible with Google C++, extern functions should only throw StatusCode error types.  The generated C++ headers could wrap Rune functions to return StatusOr<T>.  For code using C++ catch-throw, the generated interfaces should wrap the Rune function to convert the error codes to C++ classes or structs, and throw them.

There's a lot more that would need to be done to interface well with C++.  For example, we should auto-generate wrapper C++ classes for Rune non-ref-counted classes, where constructors call Rune constructors to get the usual u32 object reference, and store it as a data member in the wrapper.  All the public methods could be wrapped using the Rune object reference.

Similarly, we can generate a function API for C, and Rust struct wrappers.

Bill

Reply all
Reply to author
Forward
0 new messages