Macro cpp::cpp_class[][src]

macro_rules! cpp_class {
    ($(#[$($attrs:tt)*])* unsafe struct $name:ident as $type:expr) => { ... };
    ($(#[$($attrs:tt)*])* pub unsafe struct $name:ident as $type:expr) => { ... };
    ($(#[$($attrs:tt)*])* pub($($pub:tt)*) unsafe struct $name:ident as $type:expr) => { ... };
}

This macro allow to wrap a relocatable C++ struct or class that might have destructor or copy constructor, instantiating the Drop and Clone trait appropriately.

This example is not tested
cpp_class!(pub unsafe struct MyClass as "MyClass");
impl MyClass {
    fn new() -> Self {
        unsafe { cpp!([] -> MyClass as "MyClass" { return MyClass(); }) }
    }
    fn member_function(&self, param : i32) -> i32 {
        unsafe { cpp!([self as "const MyClass*", param as "int"] -> i32 as "int" {
            return self->member_function(param);
        }) }
    }
}

This will create a rust struct MyClass, which has the same size and alignment as the the C++ class "MyClass". It will also implement the Drop trait calling the destructor, the Clone trait calling the copy constructor, if the class is copyable (or Copy if it is trivially copyable), and Default if the class is default constructible

Derived Traits

The Default, Clone and Copy traits are implicitly implemented if the C++ type has the corresponding constructors.

You can add the #[derive(...)] attribute in the macro in order to get automatic implementation of the following traits:

  • The trait PartialEq will call the C++ operator==.
  • You can add the trait Eq if the semantics of the C++ operator are those of Eq
  • The trait PartialOrd need the C++ operator< for that type. lt, le, gt and ge will use the corresponding C++ operator if it is defined, otherwise it will fallback to the less than operator. For PartialOrd::partial_cmp, the operator< will be called twice. Note that it will never return None.
  • The trait Ord can also be specified when the semantics of the operator< corresponds to a total order

Safety Warning

Use of this macro is highly unsafe. Only certain C++ classes can be bound to, C++ classes may perform arbitrary unsafe operations, and invariants are easy to break.

A notable restriction is that this macro only works if the C++ class is relocatable, i.e., can be moved in memory using memmove.

Unfortunately, as the STL often uses internal self-references for optimization purposes, such as the small-string optimization, this disallows most std:: classes. This restriction exists because safe rust is allowed to move your types around.

Most C++ types which do not contain self-references will be compatible, although this property cannot be statically checked by rust-cpp.