Education/Learning/UnderstandingXpcomFiles: Difference between revisions

Jump to navigation Jump to search
no edit summary
No edit summary
Line 41: Line 41:
The [http://hg.mozilla.org/mozilla-central/file/0cd41f599080/xpcom/io/nsILocalFile.idl nsILocalFile.idl] file defines the interface, but not in a way useful to the C++ compiler.  In order to use it in C++, we need a proper header file.  This is where the [https://developer.mozilla.org/en/XPIDL/xpidl xpidl] compiler comes in.  One of the [https://developer.mozilla.org/index.php?title=En/How_Mozilla%27s_build_system_works jobs of the build system] during the export phase is to create .h files from .idl.
The [http://hg.mozilla.org/mozilla-central/file/0cd41f599080/xpcom/io/nsILocalFile.idl nsILocalFile.idl] file defines the interface, but not in a way useful to the C++ compiler.  In order to use it in C++, we need a proper header file.  This is where the [https://developer.mozilla.org/en/XPIDL/xpidl xpidl] compiler comes in.  One of the [https://developer.mozilla.org/index.php?title=En/How_Mozilla%27s_build_system_works jobs of the build system] during the export phase is to create .h files from .idl.


Since the build system generates nsILocalFile.h at compile time, you won't find it in the source tree, nor indexed in [http://mxr.mozilla.org MXR].  For discussion purposes, here it is: [[Education/Learning/UnderstandingXpcomFiles/nsILocalFile.h|nsILocalFile.h]].
Since the build system generates nsILocalFile.h at compile time, you won't find it in the source tree, nor indexed in [http://mxr.mozilla.org MXR].  To locate it, you'll need to compile the code yourself, and look in: '''objdir/xpcom/io/_xpidlgen''' (substitute your object directory name for ''objdir'').  For discussion purposes, here it is: [[Education/Learning/UnderstandingXpcomFiles/nsILocalFile.h|nsILocalFile.h]].  This explains why you'll see references to nsILocalFile.h throughout the tree (e.g., #include "nsILocalFile.h").


== A quick tour of nsILocalFile.h ==
One of the benefits of the build system automatically generating the header file for us, is that we can focus on writing/reading .idl and leave the dirty work of the .h file to someone else.  However, there are some interesting things in there to note.
=== NS_DECL_NSILOCALFILE ===
The first one is the macro named NS_DECL_NSILOCALFILE.  You'll see macros of this form (i.e., NS_DECL_interface-name) all over the tree.  For example, in [http://hg.mozilla.org/mozilla-central/file/0cd41f599080/xpcom/io/nsLocalFileWin.h nsLocalFileWin.h].
83 NS_DECL_NSILOCALFILE
This simplifies the declaration of the members for nsILocalFile, and explains why you won't see them in the source anywhere.  Here is what NS_DECL_NSILOCALFILE looks like:
<pre>
/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_NSILOCALFILE \
  NS_SCRIPTABLE NS_IMETHOD InitWithPath(const nsAString & filePath); \
  NS_IMETHOD InitWithNativePath(const nsACString & filePath); \
  NS_SCRIPTABLE NS_IMETHOD InitWithFile(nsILocalFile *aFile); \
  NS_SCRIPTABLE NS_IMETHOD GetFollowLinks(PRBool *aFollowLinks); \
  NS_SCRIPTABLE NS_IMETHOD SetFollowLinks(PRBool aFollowLinks); \
  NS_IMETHOD OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc * *_retval NS_OUTPARAM); \
  NS_IMETHOD OpenANSIFileDesc(const char *mode, FILE * *_retval NS_OUTPARAM); \
  NS_IMETHOD Load(PRLibrary * *_retval NS_OUTPARAM); \
  NS_SCRIPTABLE NS_IMETHOD GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable); \
  NS_SCRIPTABLE NS_IMETHOD AppendRelativePath(const nsAString & relativeFilePath); \
  NS_IMETHOD AppendRelativeNativePath(const nsACString & relativeFilePath); \
  NS_SCRIPTABLE NS_IMETHOD GetPersistentDescriptor(nsACString & aPersistentDescriptor); \
  NS_SCRIPTABLE NS_IMETHOD SetPersistentDescriptor(const nsACString & aPersistentDescriptor); \
  NS_SCRIPTABLE NS_IMETHOD Reveal(void); \
  NS_SCRIPTABLE NS_IMETHOD Launch(void); \
  NS_SCRIPTABLE NS_IMETHOD GetRelativeDescriptor(nsILocalFile *fromFile, nsACString & _retval NS_OUTPARAM); \
  NS_SCRIPTABLE NS_IMETHOD SetRelativeDescriptor(nsILocalFile *fromFile, const nsACString & relativeDesc);
</pre>
=== nsILocalFile.h Implementation Template ===
Buried within the generated [[Education/Learning/UnderstandingXpcomFiles/nsILocalFile.h|nsILocalFile.h]] is a skeleton implementation of the class in C++ that has been ifdef'ed out.  This is helpful for people learning the Mozilla source that have to add a feature to an IDL file and then write an implementation.  Here is some of what it looks like:
<pre>
#if 0
/* Use the code below as a template for the implementation class for this interface. */
/* Header file */
class nsLocalFile : public nsILocalFile
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSILOCALFILE
  nsLocalFile();
private:
  ~nsLocalFile();
protected:
  /* additional members */
};
/* Implementation file */
NS_IMPL_ISUPPORTS1(nsLocalFile, nsILocalFile)
nsLocalFile::nsLocalFile()
{
  /* member initializers and constructor code */
}
nsLocalFile::~nsLocalFile()
{
  /* destructor code */
}
/* void initWithPath (in AString filePath); */
NS_IMETHODIMP nsLocalFile::InitWithPath(const nsAString & filePath)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}
...
</pre>
=== NS_IMETHODIMP and nsresult ===
If you compare the IDL and .H for the initWithPath method, you'll see some important differences.  First, notice that initWithPath has become InitWithPath in the C++ code (it remains initWithPath to JavaScript callers).
Second, notice that where initWithPath returned '''void''' in the IDL, we now see the use of the NS_IMETHODIMP macro.  XPCOM methods are expected to return a result indicating success or failure, and in the case of failure, a specific error code.  This is done using an '''nsresult''', which is an integer value.  Many common error cases have macros, for example, NS_OK or NS_ERROR_NOT_IMPLEMENTED.  As a result of this, any IDL method that needs to return a value gets an extra argument added for the return value.  For example, '''_retval''' below:
/* ACString getRelativeDescriptor (in nsILocalFile fromFile); */
NS_IMETHODIMP nsLocalFile::GetRelativeDescriptor(nsILocalFile *fromFile,  nsACString & _retval NS_OUTPARAM)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}
=== Getters and Setters ===
It's also important to notice how IDL attributes get rewritten in C++.


still editing...
still editing...
Confirmed users
656

edits

Navigation menu