You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



IDL Author's Guide - Rules and Syntax

XPIDL (XP1 Interface Description Language) is based on the OMG IDL specification, which is used to describe CORBA interfaces. XPIDL is neither a strict superset nor a strict subset of OMG IDL, since we introduce some XPCOM-specific syntax but don't support all elements of OMG IDL syntax. This section describes the rules for describing interfaces in XPIDL. To see the C++ code generated for a given sample, click the [C++].

Interfaces
    An interface is declared with the interface keyword, and the simplest possible interface is as follows:
      interface nsIFoo {
      };
      	
    To specify an interface's parent, follow the interface name with a colon and the parent name:
      interface nsIFoo : nsIParent {
      };
      	
    In XPCOM, all interfaces have an associated IID. Use the identifier attribute syntax to specify the uuid attribute:
      [uuid(00000000-0000-0000-c000-000000000046)]
      interface nsIFoo : nsIParent {
      };
      	
    If you wish to have a forward declaration for an interface, simply omit the interface definition and all parent and attribute data:
      interface nsIForward;
              
Methods and Attributes
    An interface can have both methods and attributes. Attributes are properties of interface objects, which can be read and optionally set. The following is an interface with one method (no return value, no parameters) named fun and an integer-valued attribute named attr:
      interface nsIFoo {
          attribute long attr;
          void fun();
      };
            
    Methods can have any number of in, out or inout parameters, with a variety of types. The following interface shows parameters of different types and ``in-out-ness''2:
      interface nsIStringStuff {
        void findStringLength(in string str, out long l);
        void concatenateStrings(in string str1, in string str2,
                                out string result);
        void replaceChar(inout string str, in char from, in char to,
                         in boolean foldCase);
      };
             
    You can specify a non-void return type for your method, but you should be aware of the code-generation rules. A non-void return type is converted to a trailing out parameter when the C++ is generated :
      interface nsINonVoidReturn {
        string gimmeString(in string str, in long count);
        long gimmeLong(in boolean prime);
      };
              
    Attributes can be made read-only, by prepending the readonly keyword to the definition :
      interface nsIThing {
        readonly attribute string lookButDontTouch;
      };
              

    C++ get and set methods for attributes are automatically declared for attributes in the interface. An attribute name foo generates accessor methods GetFoo and SetFoo. Notice that the first letter of the attribute is changed to uppercase for the accessor method.

    XPIDL codeGenerated C++ header
    interface nsIBar {
      attribute short foo;
    };
    
    /* starting interface:    nsIBar */
    class nsIBar :  {
     public:
    
      /* attribute short foo; */
      NS_IMETHOD GetFoo(PRInt16 *aFoo) = 0;
      NS_IMETHOD SetFoo(PRInt16 aFoo) = 0;
    };          
    

    The xpidl compiler capitalizes method names when generating C++ headers. This is to support existing C++ convention in Mozilla, which is to use the InterCaps method naming style. The method name used in XPIDL will appear with the same capitalization to JavaScript, so the best practice is to match JavaScript convention by declaring attributes and method names in interCaps.

    XPIDL codeGenerated C++ header
    interface nsISil {
      void twiddleSil();
    };
    
    /* starting interface:    nsISil */
    class nsISil {
     public: 
    
      /* void twiddleSil (); */
      NS_IMETHOD TwiddleSil(void) = 0;
    };
    

    If for some reason the default name for a method or attribute cannot be used, say, because that name conflicts with a Windows macro, the binaryname(Name) modifier can be used to change the C++ symbol name. For example:

    XPIDL codeGenerated C++ header
    interface nsINameConflicts {
      [binaryname(MessageMoz)] attribute AString message;
      [binaryname(PostMessageMoz)] void postMessage(in AString message);
    };
    
    /* starting interface:    nsINameConflicts */
    class nsINameConflicts {
     public: 
    
      /* [binaryname(MessageMoz)] attribute AString message; */
      NS_IMETHOD GetMessageMoz(nsAString& message) = 0;
      NS_IMETHOD SetMessageMoz(const nsAString& message) = 0;
      /* [binaryname(PostMessageMoz)] void postMessage(in AString message); */
      NS_IMETHOD PostMessageMoz(const nsAString& message) = 0;
    };
    

Built-in Types

XPIDL provides several built-in types. The use of native types is also possible, though this may limit scriptability.

    TypeC++ mapping
    void void
    boolean PRBool
    octet PRUint8
    short PRInt16
    long PRInt32
    long long PRInt64
    unsigned short PRUint16
    unsigned long PRUint32
    unsigned long long PRUint64
    float float
    double double
    char char
    wchar PRUnichar
    string char*
    wstring PRUnichar*
Using native types

    It is possible to use native types in XPIDL by declaring then using the native declaration syntax which works similar to a typedef in C++.

    A native type can be given a name using the following syntax:
    native name(native_type);

    It is also possible to define reference and pointer types by combining [ref] or [ptr] with native:

    XPIDL codeGenerated C++
    [ref] native nsNativeFileRef(nsFileSpec);
    [ptr] native nsNativeFilePtr(nsFileSpec);
    
    interface foo {
      void openByRef(in nsNativeFileRef aFileSpecRef);
      void openByPtr(in nsNativeFilePtr aFileSpecPtr);
    };      
    
    /* starting interface:    foo */
    class foo {
     public:
    
      /* void openByRef (in nsNativeFileRef aFileSpecRef); */
      NS_IMETHOD OpenByRef(nsFileSpec & aFileSpecRef) = 0;
    
      /* void openByPtr (in nsNativeFilePtr aFileSpecPtr); */
      NS_IMETHOD OpenByPtr(nsFileSpec * aFileSpecPtr) = 0;
    };                                  
    

    Using native types in your code can be a good way to migrate existing interfaces. However, using native types in a method will mean that method is not scriptable.

#include
    When referencing interfaces defined in other files, you must #include "filename.idl" In XPIDL, #include only includes the file once, so the #include statement does not need to be protected by ifdefs as with the C preprocessor.
Enumerations and Constants

    C-style enumerations are not supported, since the size of enums can be compiler-specific. Instead XPIDL supports defining constants that appear in the C++ and JavaScript mappings. Constants must be of type short or long, and must appear inside an interface declaration.

    Other types are not supported for constants since they do not map into all languages or have memory management issues. To define a "constant" that is not a short or long, write a method that returns the value, or put the value into an attribute.

    XPIDL codeC++ code
    const short c1 = 1+1;enum { c1 = 2 };
    const short c2 = c1 * 5;enum { c2 = 10 };
    const long flag = 1 << 5;enum { flag = 32 };
    const float invalid_constant = 6.0;Warning: const decl 'invalid_constant' was not of type short or long, ignored

[Rules and Syntax] [Best Practices] [Keywords]


1: ``XP'' stands for ``cross-platform'', of course.
2: I crave a better name for this.

Mike Shaver
Mike Ang
Mike McCabe
Last modified: Tue Oct 5 15:33:12 PDT 1999