vtable_gen 0.1.0

A C++-ABI VTable Generator for Rust
Documentation

VTable Gen

This crate provides macros to generate C++-ABI VTables by defining the structure and vtable layout. It also supports VTable inheritance and basic class inheritance.

Examples

Check out tests.rs, which is pretty self-explanatory.

Usage

Base Structs

  • Define a structure that contains virtual functions
  • Define a structure for the VTable that exactly matches the name of the structure it belongs to, followed by VTable exactly. Example:
struct Foo {}
struct FooVTable {}
  • Mark both the VTable and structure with #[gen_vtable]. Any function pointers you include in the VTable struct will require implementation in an automatically-generated <name>Virtuals trait. Complete Example:
#[gen_vtable]
struct Foo {}
#[gen_vtable]
struct FooVTable {
    foo: extern "C" fn(this: &Foo) -> u32;
}

impl FooVirtuals for Foo {
    extern "C" fn foo(this: &Foo) -> u32 { todo!() }
}

Derived Structs

  • Define structures exactly as with base structures
  • Include the attribute base. Example:
#[gen_vtable]
struct Foo {}
#[gen_vtable]
struct FooVTable {}

#[gen_vtable(base = "Foo")]
struct Bar {}
#[gen_vtable(base = "Foo")]
struct BarVTable {}

Constructing Structs with VTables

Constructing structs with VTables is easy. If the struct is default-able, simply derive DefaultVTable instead of Default. This will impl Default. If the struct isn't default-able, define some function fn new(/* args */) -> Self. Mark the function with new_with_vtable, supplying base structs if necessary as in Derived Structs. For the compiler to know the type, you must either explicitly replace Self as the return type with the type itself, or specify self_type. Here's a verbose example:

// ...
impl Bar {
    #[new_with_vtable(self_type = "Bar")]
    fn new(baz: u32) -> Self {
        Self { baz }
    }
}

which is also equivalent to

// ...
impl Bar {
    #[new_with_vtable]
    fn new(baz: u32) -> Bar {
        Self { baz }
    }
}

If there is a base struct that requires its new function to be called, you will have to also explicitly initialize a base_with_vtbl member with the new constructor of the child type. For example:

// ...
impl Bar {
    #[new_with_vtable(base = "Foo", self_type = "Bar")]
    fn new(baz: u32) -> Self {
        Self {
            base_with_vtable: Foo::new(123),
            baz
        }
    }
}

Known Limitations

  • vtable_gen currently does not support generic structs. This is a trivial addition, however, and will likely be added in the future