Crate xpcom_macros [] [src]

This crate provides the #[derive(xpcom)] custom derive. This custom derive is used in order to implement xpcom interfaces.

Usage

The easiest way to explain this crate is probably with a usage example. I'll show you the example, and then we'll destructure it and walk through what each component is doing.

This example is not tested
// Declaring an XPCOM Struct
#[derive(xpcom)]
#[xpimplements(nsIRunnable)]
#[refcnt = "atomic"]
struct InitImplRunnable {
    i: i32,
}

// Implementing methods on an XPCOM Struct
impl ImplRunnable {
    pub fn Run(&self) -> nsresult {
        println!("{}", self.i);
        NS_OK
    }
}

Declaring an XPCOM Struct

This example is not tested
// This derive should be placed on the initialization struct in order to
// trigger the procedural macro.
#[derive(xpcom)]

// The xpimplements attribute should be passed the names of the IDL
// interfaces which you want to implement. These can be separated by commas
// if you want to implement multiple interfaces.
//
// Some methods use types which we cannot bind to in rust. Interfaces
// like those cannot be implemented, and a compile-time error will occur
// if they are listed in this attribute.
#[xpimplements(nsIRunnable)]

// The refcnt attribute can have one of the following values:
//  * "atomic" == atomic reference count
//    ~= NS_DECL_THREADSAFE_ISUPPORTS in C++
//  * "nonatomic" == non atomic reference count
//    ~= NS_DECL_ISUPPORTS in C++
//  * "cyclecollected" == cycle collected reference count
//    ~= NS_DECL_CYCLE_COLLECTING_ISUPPORTS in C++
//    (NOTE: This is not implemented yet)
#[refcnt = "atomic"]

// The struct with the attribute on its name must start with `Init`.
// The custom derive will define the actual underlying struct. For
// example, placing the derive on a struct named `InitFoo` will cause
// an underlying `Foo` struct to be generated.
//
// It is a compile time error to put the `#[derive(xpcom)]` derive on
// an enum, union, or tuple struct.
struct InitImplRunnable {
    // Fields in the `Init` struct will also be in the underlying struct.
    i: i32,
}

This will generate an underlying ImplRunnable struct, which will implement the nsIRunnable XPCOM interface. The following methods will be automatically implemented on it:

This example is not tested
// Automatic nsISupports implementation
unsafe fn AddRef(&self) -> nsrefcnt;
unsafe fn Release(&self) -> nsrefcnt;
unsafe fn QueryInterface(&self, uuid: &nsIID, result: *mut *mut libc::c_void) -> nsresult;

// Allocates and initializes a new instance of this type. The values will
// be moved from the `Init` struct which is passed in.
fn allocate(init: InitImplRunnable) -> RefPtr<Self>;

// Helper for performing the `query_interface` operation to case to a
// specific interface.
fn query_interface<T: XpCom>(&self) -> Option<RefPtr<T>>;

// Coerce function for cheaply casting to our base interfaces.
fn coerce<T: ImplRunnableCoerce>(&self) -> &T;

The RefCounted interface will also be implemented, so that the type can be used within the RefPtr type.

The coerce and query_interface methods are backed by the generated *Coerce trait. This trait is impl-ed for every interface implemented by the trait. For example:

This example is not tested
pub trait ImplRunnableCoerce {
    fn coerce_from(x: &ImplRunnable) -> &Self;
}
impl ImplRunnableCoerce for nsIRunnable { .. }
impl ImplRunnableCoerce for nsISupports { .. }

Implementing methods on an XPCOM Struct

This example is not tested
// Methods should be implemented directly on the generated struct. All
// methods other than `AddRef`, `Release`, and `QueryInterface` must be
// implemented manually.
impl ImplRunnable {
    // The method should have the same name as the corresponding C++ method.
    pub fn Run(&self) -> nsresult {
        // Fields defined on the `Init` struct will be directly on the
        // generated struct.
        println!("{}", self.i);
        NS_OK
    }
}

Functions

xpcom_internal