Confirmed users
656
edits
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... | ||