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 |