tvm_ffi

Attribute Macro rs_class

#[rs_class]
Expand description

Define an object type in Rust from its object struct, as Python’s py_class does: the type registers its key with the reflection of every field, so that C++ structural equality and hashing, repr, deep copy and Python see the fields.

ⓘ
use tvm_ffi::{def_object_ref, rs_class};

/// A pair of values under a `Base`.
#[rs_class("my_ext.Pair", final)]
pub struct PairObj {
    base: BaseObj,
    pub first: tvm_ffi::String,
    pub second: tvm_ffi::String,
    #[reflect(seq_hash_ignore)]
    pub note: tvm_ffi::String,
}

def_object_ref!(pub Pair, Base, PairObj);

let pair = Pair::from(PairObj::new(BaseObj::new(/* ... */), "a", "b", ""));
let base = Base::from(pair);

The first field, base, is the parent’s object, as the base class of a C++ object is: base: Object for a type under ffi.Object. The parent’s object must implement ShallowCopy and UnsafeInit, as rs_class types and non-final C++ types bound by tvm-ffi-stubgen do. Every other field is reflected; #[reflect(writable, seq_hash_ignore, ...)] gives a field the FieldFlags of those names, and name and doc as for derive(Object). The macro adds to the struct:

  • #[repr(C)] and Deref to the parent’s object, so obj.field reads the fields of both.
  • PairObj::new(base, ...), which builds the object from the parent’s object and the fields in order: a scalar (bool, an integer or a float) as its own type, so that a literal infers as it, and any other field from anything that converts into it, as the new of a type bound by tvm-ffi-stubgen takes them.

def_object_ref! defines the reference to it and its conversion into the reference to its parent.

After the type key:

  • final, s_eq_hash_kind = "TreeNode", child_slots = N, child_slots_can_overflow = bool and reflection = path are derive(Object)’s #[type_final], #[type_s_eq_hash_kind], #[type_child_slots], #[type_child_slots_can_overflow] and #[type_reflection].
  • crate = path is where the generated code finds tvm-ffi (crate = ::my_lib::tvm_ffi), for a crate that depends on it only through a re-export; by default tvm_ffi.

The type is a derive(Object) type with #[type_register]: it registers on its first type_index(), with the fields, the methods, __ffi_shallow_copy__ and __ffi_type_final__, and a creator that makes the object with every field undefined for reflection to set, as C++ makes one with UnsafeInit, from which it registers __ffi_new__ and, unless the methods define it, __ffi_init__; the macro implements UnsafeInit for the object. A field’s type must implement AnyCompatible and Clone; an init_off field’s type must take all-zero bytes as a value, as __ffi_init__ leaves the field so.