For support and discussion:
This document describes some dos and don'ts when writing an interface in IDL for Mozilla. For a complete guide, see the How To Freeze document.
/* don't capitalize first letters! */ void OpenFile(in nsIFile file); attribute AString Filename; /* Avoid underscores! */ attribute long unknown_entries;
void openFile(in nsIFile file); attribute AString filename; attribute long unknownEntries;
/* These refer to the same value, why make them functions? */ long getColorValue(); void setColorValue(in long value); /* we just want a getter, but we can still use an attribute! * besides, a method implies an action. */ long brightness();
attribute long colorValue; readonly attribute long brightness;
/* seems a bit verbose */ readonly attribute long numberOfEntries; /* why shorten this? is this Attribute? Attrition? */ long getAttrCount(in ACString name);
readonly attribute long entryCount; long getAttributeCount(in ACString name);
nsA-
string classes are more efficient than the "string" type./* use the new string classes! */ void processName(in string name); /* high bit will get stripped by XPConnect. is that ok? */ void fillBuffer(in string data); /* new string classes will avoid excess allocation, * especially when the caller uses nsCAutoString */ void getHeaderValues(out string prefix, out string postfix);
void processName(in ACString name); void fillBuffer(in ACString data); void getHeaderValues(out ACString prefix, out ACString postfix);
AString
or AUTF8String
to represent unicode strings. Avoid
the "wstring" type where possible.nsA-
string classes are more efficient than the old "wstring" type. /* Even if errorMsg is UTF8, it will get corrupted by XPConnect */ void displayError(in string errorMsg); /* use AString to allow fragment to have a length */ void parseFragment(in wstring fragment);
void displayError(in AUTF8String errorMsg); void parseFragment(in AString fragment);
out
parametersout
parameters are extra work for scripts, which must create a temporary object to hold the
resulting value. /* This will be frustrating to call from a script */ void getHeaderValue(in ACString header, out AString value); /* why isn't this just an attribute? */ void getLinkSource(out AString source);
AString getHeaderValue(in ACString header); readonly attribute AString linkSource;
#include
s./* Can't compile the idl file without this, we derive from nsISupports */ #include "nsISupports.idl" /* does every consumer need to also include this? */ #include "nsIAtom.idl" /* Need this for definition of PRThreadPriority */ #include "nsIThread.idl" interface nsIFoo : nsISupports { void setThreadPriority(in nsIThread thread, in PRThreadPriority pri); nsIAtom getThreadAtom(in nsIThread thread); };
/* Can't compile the idl file without this */ #include "nsISupports.idl" /* Need this for definition of PRThreadPriority */ #include "nsIThread.idl" /* Let consumers #include the right header if they need the full definition. */ interface nsIAtom; interface nsIFoo : nsISupports { ... };
#include
only other .idl files.#include
the correct header.
#include
a .h file in order to get the definition, you may have problems
with the generated header if the #include
d .h file changes later. Excessive #include
s
can also cause unnecessary rebuilding when a header changes. %{C #include "nsIArena.h" /* C++ only header */ #include "nsIThread.h" /* Available as nsIThread.idl */ %} /* now have to predeclare nsIThread since IDL doesn't know about it */ interface nsIThread;
/* If header is available (and we really need it) just #include it */ #include "nsIThread.idl" /* otherwise, predeclare it */ interface nsIArena;
// nsIFoo.idl: %{C // ugh! This doesn't belong in IDL! #define NS_FOO_CONTRACTID "@mozilla.org/foo/component;1" %}
// nsIFoo.idl contains only true IDL ...
// nsFoo.h contains the ContractID declaration: ... #define NS_FOO_CONTRACTID "@mozilla.org/foo/component;1" ...