Better C++ interoperability

It doesn’t use macros much. Most of them are just used for shortening the code. There are some features based on macros and Qt’s own C++ preprocessor (moc), and they’ll require special treatment. I think it will be possible to support everything important, though.

Qt uses overloading a lot. Overloading is emulated with traits implemented over tuples of arguments. The only drawback is that instead of writing method() and method(arg1, arg2) the user has to write method(()) and method((arg1, arg2)). Rust calls the FFI function corresponding to supplied methods automatically. This system is already implemented. I also intend to add alternative overloading method based on Option type when possible.

Inheritance is also used a lot in Qt. Supporting C++ inheritance includes 3 things:

  • Functions for downcasting and upcasting for available pointer types. Not implemented yet, but easy.
  • Methods inherited from base classes are added directly to wrappers of derived classes. It’s kind of a hack, but it provides easy access to inherited methods. It could be replaced with trait-based method injection, but I don’t like it because the user would need to bring the trait into scope.
  • Deriving from C++ classes is the most difficult, but also possible. The user will have to define extern “C” functions with specific signature and pass them to a special class constructor. These functions will be called as if they were reimplemented virtual methods of the class. The functions will receive pointers providing access to protected methods of the class. Maybe this will be made more convenient using Rust macros.

There are also issues related to automatic type conversion in C++. Functions and methods may receive pointers to base classes, and pointers to derived class will be automatically converted, but this is only one case. Qt uses automatic conversion between integers and enums, for example. Rust does not do any of this. It may be emulated with traits (like AsRef), but I’m not sure if it should be done.

Templates are my current task. Qt doesn’t use templates much. They are mostly used for vectors, smart pointers and so on. Instantiation of custom types from Rust side is currently out of the question. I want to generate wrappers for any template instantiation that can be encountered in API, in order to provide access to objects the user may acquire. I also want to organize inter-library template instantiation because Qt is separated to multiple libraries and they use templates of the QtCore library.

The bottom line is, Rust is good enough to emulate almost everything an API may need. It often is very inconvenient to do, but I’m writing an automatic code generator, so I can do things that are very inconvenient to implement but easy to use. Also, Qt’s API is really huge, and manual implementation is not an option anyway.

5 Likes