mozilla

Revision 72534 of Compiler un composant XPCOM javascript

  • Raccourci de la révision : compiler_un_composant_xpcom_javascript
  • Titre de la révision : Compiler un composant XPCOM javascript
  • ID de la révision : 72534
  • Créé :
  • Créateur : Demos
  • Version actuelle ? Non
  • Commentaire 43 words added, 44 words removed

Contenu de la révision

 

Note: Page en cours de traduction

Ceci est un tutoriel "Hello World" de création de composant XPCOM javascript. Il ne décrit pas comment ni pourquoi les XPCOMs ou chaque bit de ce code fonctionnent de cette manière. Cela a déjà été fait ailleurs (en). En revanche, est décrite, ici, la façon de faire marcher un composant en un minimum d'étapes, les plus simples possibles. 

Implementation

Cet exemple de composant fournit une seule méthode retournant la chaine "Hello World!".

Définition de l'Interface

If you want to use your component in other XPCOM components, you must define the interfaces that you want exposed. If you want to use your component only from JavaScript, you can skip to the next section.

There are many interfaces already defined in Mozilla applications, so you may not need to define a new one. You can browse existing XPCOM interfaces at various locations in the Mozilla source code, or using XPCOMViewer, a GUI for browsing registered interfaces and components. You can download an old version of XPCOMViewer that works with Firefox 1.5 from mozdev mirrors.

If an interface exists that meets your needs, then you do not need to write an IDL, or compile a typelib, and may skip to the next section.

If you don't find a suitable pre-existing interface, then you must define your own. XPCOM uses a dialect of IDL to define interfaces, called XPIDL. Here's the XPIDL definition for our HelloWorld component:

HelloWorld.idl

#include "nsISupports.idl"

[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]
interface nsIHelloWorld : nsISupports
{
  string hello();
};  

Note that you must generate a new UUID for each XPCOM component that you create. See Generating GUIDs for more information.

Compilation de la Typelib

La définition de votre interface doit être compilée en format binaire (XPT) pour être prise en compte et exploitable dans les applications Mozilla. Cette compilation peut se faire avec le SDK Gecko. Vous en trouverez les versions Linux, Mac et Windows en lisant l'article Gecko SDK (en).

Note: On Windows if you download the Gecko SDK without the whole build tree, you will be missing some required DLLs for xpidl.exe and it will run with no errors but not do anything. To fix this download the Mozilla build tools for Windows and copy the DLLs from windows\bin\x86 within the zip into the bin directory of the Gecko SDK.
Note: The Mac version of the SDK provided for download is PowerPC-only. If you need an Intel version, you'll need to compile it yourself as described on that page.

Execute this command to compile the typelib. Here, {sdk_dir} is the directory in which you unpacked the Gecko SDK.

{sdk_dir}/bin/xpidl -m typelib -w -v -I {sdk_dir}/idl -e HelloWorld.xpt HelloWorld.idl

  

Note: On Windows you must use forward slashes for the include path.

(The -I flag is an uppercase i, not a lowercase L.) This will create the typelib file HelloWorld.xpt in the current working directory.

Création du Composant

HelloWorld.js

/***********************************************************
constants
***********************************************************/

// reference to the interface defined in nsIHelloWorld.idl
const nsIHelloWorld = Components.interfaces.nsIHelloWorld;

// reference to the required base interface that all components must support
const nsISupports = Components.interfaces.nsISupports;

// UUID uniquely identifying our component
// You can get from: http://kruithof.xs4all.nl/uuid/uuidgen here
const CLASS_ID = Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}");

// description
const CLASS_NAME = "My Hello World Javascript XPCOM Component";

// textual unique identifier
const CONTRACT_ID = "@dietrich.ganx4.com/helloworld;1";

/***********************************************************
class definition
***********************************************************/

//class constructor
function HelloWorld() {
// If you only need to access your component from Javascript, uncomment the following line:
//this.wrappedJSObject = this;
}

// class definition
HelloWorld.prototype = {

  // define the function we want to expose in our interface
  hello: function() {
      return "Hello World!";
  },

  QueryInterface: function(aIID)
  {
    if (!aIID.equals(nsIHelloWorld) &&    
        !aIID.equals(nsISupports))
      throw Components.results.NS_ERROR_NO_INTERFACE;
    return this;
  }
};

/***********************************************************
class factory

This object is a member of the global-scope Components.classes.
It is keyed off of the contract ID. Eg:

myHelloWorld = Components.classes["@dietrich.ganx4.com/helloworld;1"].
                          createInstance(Components.interfaces.nsIHelloWorld);

***********************************************************/
var HelloWorldFactory = {
  createInstance: function (aOuter, aIID)
  {
    if (aOuter != null)
      throw Components.results.NS_ERROR_NO_AGGREGATION;
    return (new HelloWorld()).QueryInterface(aIID);
  }
};

/***********************************************************
module definition (xpcom registration)
***********************************************************/
var HelloWorldModule = {
  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
  {
    aCompMgr = aCompMgr.
        QueryInterface(Components.interfaces.nsIComponentRegistrar);
    aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, 
        CONTRACT_ID, aFileSpec, aLocation, aType);
  },

  unregisterSelf: function(aCompMgr, aLocation, aType)
  {
    aCompMgr = aCompMgr.
        QueryInterface(Components.interfaces.nsIComponentRegistrar);
    aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);        
  },
  
  getClassObject: function(aCompMgr, aCID, aIID)
  {
    if (!aIID.equals(Components.interfaces.nsIFactory))
      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

    if (aCID.equals(CLASS_ID))
      return HelloWorldFactory;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  canUnload: function(aCompMgr) { return true; }
};

/***********************************************************
module initialization

When the application registers the component, this function
is called.
***********************************************************/
function NSGetModule(aCompMgr, aFileSpec) { return HelloWorldModule; }

Utilisation de XPCOMUtils

{{ Fx_minversion_inline("3") }} In Firefox 3 and later you can use import XPCOMUtils.jsm using Components.utils.import to simplify the process of writing your component slightly. The imported library contains functions for generating the module, factory, and the NSGetModule and QueryInterface functions for you. Note: it doesn't do the work of creating your interface definition file or the type library for you, so you still have to go through those steps above if they haven't been done. The library provides a simple example of its use in the source code ({{ Source("js/src/xpconnect/loader/XPCOMUtils.jsm") }}), but here's another using this example. To begin, include a line at the top of your interface to import the XPCOMUtils library:

 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

then implement your interface the same way you did above, except with a few modifications so that XPCOMUtils can set it up properly:

/***********************************************************
class definition
***********************************************************/

//class constructor
function HelloWorld() {
// If you only need to access your component from Javascript, uncomment the following line:
//this.wrappedJSObject = this;
}

// class definition
HelloWorld.prototype = {

  // properties required for XPCOM registration:
  classDescription: "My Hello World Javascript XPCOM Component",
  classID:          Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
  contractID:       "@dietrich.ganx4.com/helloworld;1",

  // [optional] custom factory (an object implementing nsIFactory). If not
  // provided, the default factory is used, which returns
  // |(new MyComponent()).QueryInterface(iid)| in its createInstance().
  _xpcom_factory: { ... },

  // [optional] an array of categories to register this component in.
  _xpcom_categories: [{

    // Each object in the array specifies the parameters to pass to
    // nsICategoryManager.addCategoryEntry(). 'true' is passed for both
    // aPersist and aReplace params.
    category: "some-category",

    // optional, defaults to the object's classDescription
    entry: "entry name",

    // optional, defaults to the object's contractID (unless 'service' is specified)
    value: "...",

    // optional, defaults to false. When set to true, and only if 'value' is not
    // specified, the concatenation of the string "service," and the object's contractID
    // is passed as aValue parameter of addCategoryEntry.
     service: true
  }],

  // QueryInterface implementation, e.g. using the generateQI helper (remove argument if skipped steps above)
  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIHelloWorld]),

  // ...component implementation...
  // define the function we want to expose in our interface
  hello: function() {
      return "Hello World!";
  },
};

XPCOMUtils does the work of creating the module and factory for you after this. Finally, you create an array of your components to be created:

 var components = [HelloWorld];

and update NSGetModule to use this array and XPCOMUtils:

 function NSGetModule(compMgr, fileSpec) {
   return XPCOMUtils.generateModule(components);
 }

So the total simplified version of your component now looks like (of course documentation and comments aren't a bad thing, but as a template something smaller is nice to have):

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

function HelloWorld() { }

HelloWorld.prototype = {
  classDescription: "My Hello World Javascript XPCOM Component",
  classID:          Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
  contractID:       "@dietrich.ganx4.com/helloworld;1",
  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIHelloWorld]),
  hello: function() { return "Hello World!"; }
};
var components = [HelloWorld];
function NSGetModule(compMgr, fileSpec) {
  return XPCOMUtils.generateModule(components);
}
Note: NSGetModule is depreciated since Gecko 2.0 and is replaced by NSGetFactory. See XPCOM_changes_in_Gecko_2.0 for more details.


Installation

Pour les extensions:

  1. Copy HelloWorld.js, and HelloWorld.xpt (only if you defined and compiled the IDL) to {extensiondir}/components/
  2. Delete compreg.dat and xpti.dat from your profile directory.
  3. Restart application.

Pour Firefox:

  1. Copy HelloWorld.js, and HelloWorld.xpt (only if you defined and compiled the IDL) to the {objdir}/dist/bin/components directory, if running from the source.
  2. Delete compreg.dat and xpti.dat from the components directory.
  3. Delete compreg.dat and xpti.dat from your profile directory.
  4. Restart application.

Utilisation de votre Composant

Avec wrappedJSObject

If you only intend to access your component from Javascript, i.e. you skipped the sections "Defining the Interface" and "Compiling the Typelib" above, you uncommented the "wrappedJSObject" line in the class constructor, and you removed the "[Components.interfaces.nsIHelloWorld]" argument for the call to XPCOMUtils.generateQI() in QueryInterface, then you can access your component like this:

try {
        var myComponent = Components.classes['@dietrich.ganx4.com/helloworld;1']
                                    .getService().wrappedJSObject;

        alert(myComponent.hello());
} catch (anError) {
        dump("ERROR: " + anError);
}

For more information about wrappedJSObject, see here.

Avec instantiation du XPCOM

try {
        var myComponent = Components.classes['@dietrich.ganx4.com/helloworld;1']
                                    .createInstance(Components.interfaces.nsIHelloWorld);

        alert(myComponent.hello());
} catch (anError) {
        dump("ERROR: " + anError);
}

Autres resources

{{ languages( { "zh-cn": "cn/How_to_Build_an_XPCOM_Component_in_Javascript", "ja": "ja/How_to_Build_an_XPCOM_Component_in_Javascript", "en": "en/How_to_Build_an_XPCOM_Component_in_Javascript" } ) }}

Source de la révision

<p> </p>
<div class="note"><strong>Note:</strong> Page en cours de traduction</div>
<p>Ceci est un tutoriel "Hello World" de création de composant XPCOM javascript. Il ne décrit pas comment ni pourquoi les XPCOMs ou chaque bit de ce code fonctionnent de cette manière. Cela a déjà été fait <a href="/en/XPCOM" title="en/XPCOM">ailleurs (en)</a>. En revanche, est décrite, ici, la façon de faire <em>marcher</em> un composant en un minimum d'étapes, les plus simples possibles. </p>
<h2 name="Implementation">Implementation</h2>
<p>Cet exemple de composant fournit une seule méthode retournant la chaine "Hello World!".</p>
<h3 name="Defining_the_Interface">Définition de l'Interface</h3>
<p>If you want to use your component in other XPCOM components, you must define the interfaces that you want exposed. If you want to use your component <em>only</em> from JavaScript, you can skip to the <a href="#Creating_the_Component">next section</a>.</p>
<p>There are many interfaces already defined in Mozilla applications, so you may not need to define a new one. You can browse existing XPCOM interfaces at various locations in the Mozilla source code, or using <a class="external" href="http://xpcomviewer.mozdev.org/">XPCOMViewer</a>, a GUI for browsing registered interfaces and components. You can download an old version of XPCOMViewer that works with Firefox 1.5 from <a class="external" href="http://downloads.mozdev.org/xpcomviewer/">mozdev mirrors</a>.</p>
<p>If an interface exists that meets your needs, then you do not need to write an IDL, or compile a typelib, and may skip to the <a href="#Creating_the_Component">next section</a>.</p>
<p>If you don't find a suitable pre-existing interface, then you must define your own. XPCOM uses a dialect of IDL to define interfaces, called <a href="/en/XPIDL" title="en/XPIDL">XPIDL</a>. Here's the XPIDL definition for our HelloWorld component:</p>
<p>HelloWorld.idl</p>
<pre>#include "nsISupports.idl"

[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]
interface nsIHelloWorld : nsISupports
{
  string hello();
};  
</pre>
<p>Note that you must generate a new UUID for each XPCOM component that you create. See <a href="/en/Generating_GUIDs" title="en/Generating_GUIDs">Generating GUIDs</a> for more information.</p>
<h3 name="Compiling_the_Typelib">Compilation de la Typelib</h3>
<p>La définition de votre interface doit être compilée en format binaire (XPT) pour être prise en compte et exploitable dans les applications Mozilla. Cette compilation peut se faire avec le SDK Gecko. Vous en trouverez les versions Linux, Mac et Windows en lisant l'article <a href="/en/Gecko_SDK" title="en/Gecko_SDK">Gecko SDK (en)</a>.</p>
<div class="note"><strong>Note:</strong> On Windows if you download the Gecko SDK without the whole build tree, you will be missing some required DLLs for xpidl.exe and it will run with no errors but not do anything. To fix this download the <a class="external" href="http://ftp.mozilla.org/pub/mozilla.org/mozilla/source/wintools.zip">Mozilla build tools for Windows</a> and copy the DLLs from <code>windows\bin\x86</code> within the zip into the <code>bin</code> directory of the Gecko SDK.</div>
<div class="note"><strong>Note:</strong> The Mac version of the SDK provided for download is PowerPC-only. If you need an Intel version, you'll need to compile it yourself as described on that page.</div>
<p>Execute this command to compile the typelib. Here, <code>{sdk_dir}</code> is the directory in which you unpacked the Gecko SDK.</p>
<pre class="eval">{sdk_dir}/bin/xpidl -m typelib -w -v -I {sdk_dir}/idl -e HelloWorld.xpt HelloWorld.idl
</pre>
<p>  </p>
<div class="note"><strong>Note:</strong> On Windows you must use forward slashes for the include path.</div>
<p>(The -I flag is an uppercase i, not a lowercase L.) This will create the typelib file HelloWorld.xpt in the current working directory.</p><h3 name="Creating_the_Component">Création du Composant</h3>
<p>HelloWorld.js</p>
<pre class="deki-transform">/***********************************************************
constants
***********************************************************/

// reference to the interface defined in nsIHelloWorld.idl
const nsIHelloWorld = Components.interfaces.nsIHelloWorld;

// reference to the required base interface that all components must support
const nsISupports = Components.interfaces.nsISupports;

// UUID uniquely identifying our component
// You can get from: http://kruithof.xs4all.nl/uuid/uuidgen here
const CLASS_ID = Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}");

// description
const CLASS_NAME = "My Hello World Javascript XPCOM Component";

// textual unique identifier
const CONTRACT_ID = "@dietrich.ganx4.com/helloworld;1";

/***********************************************************
class definition
***********************************************************/

//class constructor
function HelloWorld() {
// If you only need to access your component from Javascript, uncomment the following line:
//this.wrappedJSObject = this;
}

// class definition
HelloWorld.prototype = {

  // define the function we want to expose in our interface
  hello: function() {
      return "Hello World!";
  },

  QueryInterface: function(aIID)
  {
    if (!aIID.equals(nsIHelloWorld) &amp;&amp;    
        !aIID.equals(nsISupports))
      throw Components.results.NS_ERROR_NO_INTERFACE;
    return this;
  }
};

/***********************************************************
class factory

This object is a member of the global-scope Components.classes.
It is keyed off of the contract ID. Eg:

myHelloWorld = Components.classes["@dietrich.ganx4.com/helloworld;1"].
                          createInstance(Components.interfaces.nsIHelloWorld);

***********************************************************/
var HelloWorldFactory = {
  createInstance: function (aOuter, aIID)
  {
    if (aOuter != null)
      throw Components.results.NS_ERROR_NO_AGGREGATION;
    return (new HelloWorld()).QueryInterface(aIID);
  }
};

/***********************************************************
module definition (xpcom registration)
***********************************************************/
var HelloWorldModule = {
  registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
  {
    aCompMgr = aCompMgr.
        QueryInterface(Components.interfaces.nsIComponentRegistrar);
    aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, 
        CONTRACT_ID, aFileSpec, aLocation, aType);
  },

  unregisterSelf: function(aCompMgr, aLocation, aType)
  {
    aCompMgr = aCompMgr.
        QueryInterface(Components.interfaces.nsIComponentRegistrar);
    aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);        
  },
  
  getClassObject: function(aCompMgr, aCID, aIID)
  {
    if (!aIID.equals(Components.interfaces.nsIFactory))
      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

    if (aCID.equals(CLASS_ID))
      return HelloWorldFactory;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  canUnload: function(aCompMgr) { return true; }
};

/***********************************************************
module initialization

When the application registers the component, this function
is called.
***********************************************************/
function NSGetModule(aCompMgr, aFileSpec) { return HelloWorldModule; }

</pre>
<h3 name="Using_XPCOMUtils">Utilisation de XPCOMUtils</h3>
<p>{{ Fx_minversion_inline("3") }} In <a href="/en/Firefox_3_for_developers" title="en/Firefox_3_for_developers">Firefox 3</a> and later you can use import <a href="/en/JavaScript_code_modules/XPCOMUtils.jsm" title="en/XPCOMUtils.jsm">XPCOMUtils.jsm</a> using <a href="/en/Components.utils.import" title="en/Components.utils.import">Components.utils.import</a> to simplify the process of writing your component slightly. The imported library contains functions for generating the module, factory, and the NSGetModule and QueryInterface functions for you. <strong>Note:</strong> it doesn't do the work of creating your interface definition file or the type library for you, so you still have to go through those steps above if they haven't been done. The library provides a simple example of its use in the source code ({{ Source("js/src/xpconnect/loader/XPCOMUtils.jsm") }}), but here's another using this example. To begin, include a line at the top of your interface to import the <code>XPCOMUtils</code> library:</p>
<pre class="eval deki-transform"> Components.utils.import("<a class=" external" href="resource://gre/modules/XPCOMUtils.jsm" rel="freelink">resource://gre/modules/XPCOMUtils.jsm</a>");
</pre>
<p>then implement your interface the same way you did above, except with a few modifications so that <code>XPCOMUtils</code> can set it up properly:</p>
<pre class="deki-transform">/***********************************************************
class definition
***********************************************************/

//class constructor
function HelloWorld() {
// If you only need to access your component from Javascript, uncomment the following line:
//this.wrappedJSObject = this;
}

// class definition
HelloWorld.prototype = {

  // properties required for XPCOM registration:
  classDescription: "My Hello World Javascript XPCOM Component",
  classID:          Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
  contractID:       "@dietrich.ganx4.com/helloworld;1",

  // [optional] custom factory (an object implementing nsIFactory). If not
  // provided, the default factory is used, which returns
  // |(new MyComponent()).QueryInterface(iid)| in its createInstance().
  _xpcom_factory: { ... },

  // [optional] an array of categories to register this component in.
  _xpcom_categories: [{

    // Each object in the array specifies the parameters to pass to
    // nsICategoryManager.addCategoryEntry(). 'true' is passed for both
    // aPersist and aReplace params.
    category: "some-category",

    // optional, defaults to the object's classDescription
    entry: "entry name",

    // optional, defaults to the object's contractID (unless 'service' is specified)
    value: "...",

    // optional, defaults to false. When set to true, and only if 'value' is not
    // specified, the concatenation of the string "service," and the object's contractID
    // is passed as aValue parameter of addCategoryEntry.
     service: true
  }],

  // QueryInterface implementation, e.g. using the generateQI helper (remove argument if skipped steps above)
  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIHelloWorld]),

  // ...component implementation...
  // define the function we want to expose in our interface
  hello: function() {
      return "Hello World!";
  },
};
</pre>
<p><code>XPCOMUtils</code> does the work of creating the module and factory for you after this. Finally, you create an array of your components to be created:</p>
<pre class="eval deki-transform"> var components = [HelloWorld];
</pre>
<p>and update NSGetModule to use this array and <code>XPCOMUtils</code>:</p>
<pre class="eval deki-transform"> function NSGetModule(compMgr, fileSpec) {
   return XPCOMUtils.generateModule(components);
 }
</pre>
<p>So the total simplified version of your component now looks like (of course documentation and comments aren't a bad thing, but as a template something smaller is nice to have):</p>
<pre class="deki-transform">Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

function HelloWorld() { }

HelloWorld.prototype = {
  classDescription: "My Hello World Javascript XPCOM Component",
  classID:          Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
  contractID:       "@dietrich.ganx4.com/helloworld;1",
  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIHelloWorld]),
  hello: function() { return "Hello World!"; }
};
var components = [HelloWorld];
function NSGetModule(compMgr, fileSpec) {
  return XPCOMUtils.generateModule(components);
}
</pre>
<div class="note"><strong>Note:</strong> NSGetModule is depreciated since Gecko 2.0 and is replaced by NSGetFactory. See <a href="/en/XPCOM/XPCOM_changes_in_Gecko_2.0" title="en/XPCOM/XPCOM_changes_in_Gecko_2.0">XPCOM_changes_in_Gecko_2.0</a> for more details.</div>
<h2 name="Installation"><br> Installation</h2>
<h3 name="For_extensions:">Pour les extensions:</h3>
<ol> <li>Copy HelloWorld.js, and HelloWorld.xpt (only if you defined and compiled the IDL) to {extensiondir}/components/</li> <li>Delete compreg.dat and xpti.dat from your profile directory.</li> <li>Restart application.</li>
</ol>
<h3 name="For_Firefox">Pour Firefox:</h3>
<ol> <li>Copy HelloWorld.js, and HelloWorld.xpt (only if you defined and compiled the IDL) to the {objdir}/dist/bin/components directory, if running from the source.</li> <li>Delete compreg.dat and xpti.dat from the components directory.</li> <li>Delete compreg.dat and xpti.dat from your profile directory.</li> <li>Restart application.</li>
</ol>
<h2 name="Using_Your_Component">Utilisation de votre Composant</h2>
<h3 name="Using_wrappedJSObject">Avec wrappedJSObject</h3>
<p>If you only intend to access your component from Javascript, i.e. you skipped the sections "Defining the Interface" and "Compiling the Typelib" above, you uncommented the "wrappedJSObject" line in the class constructor, and you removed the "[Components.interfaces.nsIHelloWorld]" argument for the call to XPCOMUtils.generateQI() in QueryInterface, then you can access your component like this:</p>
<pre class="deki-transform">try {
        var myComponent = Components.classes['@dietrich.ganx4.com/helloworld;1']
                                    .getService().wrappedJSObject;

        alert(myComponent.hello());
} catch (anError) {
        dump("ERROR: " + anError);
}
</pre>
<p>For more information about wrappedJSObject, see <a href="/en/wrappedJSObject" title="en/wrappedJSObject">here</a>.</p>
<h3 name="Using_XPCOM_instantiation">Avec instantiation du XPCOM</h3>
<pre class="deki-transform">try {
        var myComponent = Components.classes['@dietrich.ganx4.com/helloworld;1']
                                    .createInstance(Components.interfaces.nsIHelloWorld);

        alert(myComponent.hello());
} catch (anError) {
        dump("ERROR: " + anError);
}
</pre>
<h2 name="Other_resources">Autres resources</h2>
<ul> <li>Two mozillazine forums threads about implementing XPCOM components in JS with some explanations, example code, and troubleshooting tips: <ul> <li><a class=" external" href="http://forums.mozillazine.org/viewtopic.php?t=308369" rel="freelink">http://forums.mozillazine.org/viewtopic.php?t=308369</a></li> <li><a class=" external" href="http://forums.mozillazine.org/viewtopic.php?t=367298" rel="freelink">http://forums.mozillazine.org/viewtopic.php?t=367298</a></li> </ul> </li> <li><a class="external" href="http://kb.mozillazine.org/Implementing_XPCOM_components_in_JavaScript">Implementing XPCOM components in JavaScript</a> at kb.mozillazine.org</li> <li><a class="external" href="http://www.mozilla.org/scriptable/avoiding-leaks.html">Using XPCOM in JavaScript without leaking</a> - A must-read.</li> <li><a class="external" href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsSample.js">An example component</a></li> <li><a class="external" href="http://www.mozilla.org/scriptable/js-components-status.html">Older JS+XPCOM notes</a> - includes some wrappedJSObject information.</li> <li><a class="external" href="http://weblogs.mozillazine.org/weirdal/archives/019620.html" title="http://weblogs.mozillazine.org/weirdal/archives/019620.html">Writing an XPCOM <em><u>Service</u></em> in javascript</a></li>
</ul>
<p>{{ languages( { "zh-cn": "cn/How_to_Build_an_XPCOM_Component_in_Javascript", "ja": "ja/How_to_Build_an_XPCOM_Component_in_Javascript", "en": "en/How_to_Build_an_XPCOM_Component_in_Javascript" } ) }}</p>
Revenir à cette révision