Skip to main content

Crate vtable_rs

Crate vtable_rs 

Source
Expand description

Attribute proc macro that can be used to turn a dyn-compatible trait definition into a C++ compatible vtable definition.

Mainly intended for making mods/memory hacking C++ applications.

For a usage example, say we have a C++ abstract class of the form

struct Obj {
    uint32_t field;

    virtual ~Obj() = default;
    virtual uint32_t method(uint32_t arg) const noexcept = 0;
};

This macro then allows us to represent Obj’s virtual function table in Rust and provide our own implementations:

use core::ffi::c_char;
use vtable_rs::{vtable, VPtr};

#[vtable]
pub trait ObjVmt<T: Clone> {
    /// The proper way to write this function would be to take self as a raw pointer, that is
    /// `self: *mut Self`. Unfortunately, this requires the `arbitrary_self_types` nightly feature.
    /// 
    /// # Safety
    /// Calling this from Rust is always unsound. Must be called from C++.
    unsafe fn destructor(&mut self) {
        unsafe { core::ptr::drop_in_place(self) };
    }

    fn method(&self, arg: T) -> u32;
}

// VPtr implements Default for types that implement the trait, and provides
// a compile-time generated vtable!
#[derive(Default)]
#[repr(C)]
struct RustObj {
    vftable: VPtr<dyn ObjVmt<u32>, Self>,
    field: u32
}

impl ObjVmt<u32> for RustObj {
    extern "C" fn method(&self, arg: u32) -> u32 {
        self.field + arg
    }
}

// `RustObj` could then be passed to a C++ function that takes in a pointer to `Obj`.

// Single inheritance through a trait bound, is supported:.
#[vtable]
pub trait DerivedObjVmt<T: Clone>: ObjVmt<T> {
    unsafe fn additional_method(&mut self, s: *const c_char);
}

// The vtable layout is fully typed and can be accessed as `<dyn TraitName as VmtLayout>::Layout<T>`.
// A `VPtr` can be `Deref`'d into it to obtain the bare function pointers and thus call through
// the vtable directly:

let obj = RustObj::default();
let method_impl = obj.vftable.method; // extern "C" fn(&RustObj, u32) -> u32
let call_result = method_impl(&obj, 42);

Structs§

VPtr

Traits§

VmtInstance
Provides compile-time virtual method table references for the concrete type T.
VmtLayout
Provides concrete virtual method table layouts for a vtable trait.

Functions§

vmt_instance

Attribute Macros§

vtable
Attribute proc macro that can be used to turn a dyn-compatible trait definition into a C++ compatible vtable definition.