tutorial.html revision 16a8d09569a2ebd598cef72fa605be6fb4563607
da97433d5cd26e422a370d186f98659383c06721csovant<!-- ***** BEGIN LICENSE BLOCK *****
da97433d5cd26e422a370d186f98659383c06721csovant - The contents of this file are subject to the Mozilla Public License Version
da97433d5cd26e422a370d186f98659383c06721csovant - 1.1 (the "License"); you may not use this file except in compliance with
da97433d5cd26e422a370d186f98659383c06721csovant - the License. You may obtain a copy of the License at
da97433d5cd26e422a370d186f98659383c06721csovant - Software distributed under the License is distributed on an "AS IS" basis,
da97433d5cd26e422a370d186f98659383c06721csovant - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
da97433d5cd26e422a370d186f98659383c06721csovant - for the specific language governing rights and limitations under the
3437829f938dbb44527d91fbbc5f430a1243c5a5JnRouvignac - The Original Code is PyXPCOM.
3437829f938dbb44527d91fbbc5f430a1243c5a5JnRouvignac - The Initial Developer of the Original Code is
da97433d5cd26e422a370d186f98659383c06721csovant - ActiveState Tool Corporation.
da97433d5cd26e422a370d186f98659383c06721csovant - Portions created by the Initial Developer are Copyright (C) 2000-2001
da97433d5cd26e422a370d186f98659383c06721csovant - the Initial Developer. All Rights Reserved.
da97433d5cd26e422a370d186f98659383c06721csovant - Contributor(s):
da97433d5cd26e422a370d186f98659383c06721csovant - Alternatively, the contents of this file may be used under the terms of
da97433d5cd26e422a370d186f98659383c06721csovant - either the GNU General Public License Version 2 or later (the "GPL"), or
da97433d5cd26e422a370d186f98659383c06721csovant - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
da97433d5cd26e422a370d186f98659383c06721csovant - in which case the provisions of the GPL or the LGPL are applicable instead
da97433d5cd26e422a370d186f98659383c06721csovant - of those above. If you wish to allow use of your version of this file only
da97433d5cd26e422a370d186f98659383c06721csovant - under the terms of either the GPL or the LGPL, and not to allow others to
da97433d5cd26e422a370d186f98659383c06721csovant - use your version of this file under the terms of the MPL, indicate your
da97433d5cd26e422a370d186f98659383c06721csovant - decision by deleting the provisions above and replace them with the notice
da97433d5cd26e422a370d186f98659383c06721csovant - and other provisions required by the LGPL or the GPL. If you do not delete
da97433d5cd26e422a370d186f98659383c06721csovant - the provisions above, a recipient may use your version of this file under
da97433d5cd26e422a370d186f98659383c06721csovant - the terms of any one of the MPL, the GPL or the LGPL.
da97433d5cd26e422a370d186f98659383c06721csovant - ***** END LICENSE BLOCK ***** -->
da97433d5cd26e422a370d186f98659383c06721csovant<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
da97433d5cd26e422a370d186f98659383c06721csovant<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
da97433d5cd26e422a370d186f98659383c06721csovant<meta name="ProgId" content="FrontPage.Editor.Document">
da97433d5cd26e422a370d186f98659383c06721csovant<p>This is a quick introduction to the Python XPCOM Package. We assume that you have a good understanding of Python and <a href="http://www.mozilla.org/projects/xpcom/">XPCOM</a>,
da97433d5cd26e422a370d186f98659383c06721csovantand have experience both using and implementing XPCOM objects in some other
da97433d5cd26e422a370d186f98659383c06721csovantlanguage (e.g., C++ or JavaScript). We <b><i>do not</i></b> attempt to
da97433d5cd26e422a370d186f98659383c06721csovantprovide a tutorial to XPCOM or Python itself, only to using Python <i>and</i>
da97433d5cd26e422a370d186f98659383c06721csovant<p>This tutorial contains the following sections:</p>
da97433d5cd26e422a370d186f98659383c06721csovant <li><a href="#Using">Using XPCOM Objects and Interfaces</a> - when you wish to
da97433d5cd26e422a370d186f98659383c06721csovant <i>use</i> a component written by anyone else in any XPCOM supported
da97433d5cd26e422a370d186f98659383c06721csovant language.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li><a href="#Implementing">Implementing XPCOM Objects and Interfaces</a> -
da97433d5cd26e422a370d186f98659383c06721csovant when you wish to implement a component for use by anyone else in any xpcom
da97433d5cd26e422a370d186f98659383c06721csovant supported language.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li><a href="#Parameters">Parameters and Types</a> - useful information
da97433d5cd26e422a370d186f98659383c06721csovant regarding how Python translates XPCOM types, and handles byref parameters.</li>
da97433d5cd26e422a370d186f98659383c06721csovant<p>For anything not covered here, try the <a href="advanced.html">advanced
da97433d5cd26e422a370d186f98659383c06721csovantdocumentation</a>, and if that fails, use the source, Luke!</p>
da97433d5cd26e422a370d186f98659383c06721csovant<h2><a name="Using">Using XPCOM object and interfaces.</a></h2>
da97433d5cd26e422a370d186f98659383c06721csovant<p>The techniques for using XPCOM in Python have been borrowed from JavaScript -
da97433d5cd26e422a370d186f98659383c06721csovantthus, the model described here should be quite familiar to existing JavaScript
da97433d5cd26e422a370d186f98659383c06721csovantXPCOM programmers.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<p>When using an XPCOM object, the primary module used is the <u><i>xpcom.components</i></u>
da97433d5cd26e422a370d186f98659383c06721csovant module. Using this module, you can get a Python object that supports any
da97433d5cd26e422a370d186f98659383c06721csovantscriptable XPCOM interface. Once you have this Python object, you can
da97433d5cd26e422a370d186f98659383c06721csovantsimply call XPCOM methods on the object, as normal.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<p>The <u><i>xpcom.components</i></u> module defines the following public
da97433d5cd26e422a370d186f98659383c06721csovantmembers:</p>
da97433d5cd26e422a370d186f98659383c06721csovant <td width="84%">A mapping (dictionary-like object) used to get XPCOM
da97433d5cd26e422a370d186f98659383c06721csovant "classes". These are indexed by XPCOM contract ID, just
da97433d5cd26e422a370d186f98659383c06721csovant like the JavaScript object of the same name.
da97433d5cd26e422a370d186f98659383c06721csovant <pre>cls = components.classes["@mozilla.org/sample;1"]
da97433d5cd26e422a370d186f98659383c06721csovantob = cls.createInstance() # Now have an nsISupports</pre>
da97433d5cd26e422a370d186f98659383c06721csovant <td width="84%">An object that exposes all XPCOM interface IDs (IIDs).
da97433d5cd26e422a370d186f98659383c06721csovant Like the JavaScript object of the same name, this object uses
da97433d5cd26e422a370d186f98659383c06721csovant "dot" notation, as demonstrated below.
da97433d5cd26e422a370d186f98659383c06721csovant <pre>ob = cls.createInstance(components.interfaces.nsISample)
da97433d5cd26e422a370d186f98659383c06721csovant# Now have an nsISample</pre>
da97433d5cd26e422a370d186f98659383c06721csovant<p>For many people, this is all you need to know. Consider the Mozilla Sample Component. The Mozilla Sample
da97433d5cd26e422a370d186f98659383c06721csovantComponent has a contract ID of <i>@mozilla.org/sample;1</i>,
da97433d5cd26e422a370d186f98659383c06721csovant<p>Thus, a complete Python program that uses this component is shown below.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<pre>from xpcom import components
da97433d5cd26e422a370d186f98659383c06721csovantcls = components.classes["@mozilla.org/sample;1"]
da97433d5cd26e422a370d186f98659383c06721csovantob = cls.createInstance() # no need to specify an IID for most components
da97433d5cd26e422a370d186f98659383c06721csovant# nsISample defines a "value" property - let's use it!
da97433d5cd26e422a370d186f98659383c06721csovantob.value = "new value"
da97433d5cd26e422a370d186f98659383c06721csovantif ob.value != "new value":
da97433d5cd26e422a370d186f98659383c06721csovant print "Eeek - what happened?"</pre>
da97433d5cd26e422a370d186f98659383c06721csovant<p>And that is it - a complete Python program that uses XPCOM.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<h2><a name="Implementing">Implementing XPCOM Objects and Interfaces.</a></h2>
da97433d5cd26e422a370d186f98659383c06721csovant<p>Implementing XPCOM objects is almost as simple as using them. The
da97433d5cd26e422a370d186f98659383c06721csovantbasic strategy is this:</p>
da97433d5cd26e422a370d186f98659383c06721csovant <li>Create a standard Python source file, with a standard Python class.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li>Add some special <a href="#Attributes"> attributes</a> to your class for use by the Python XPCOM
da97433d5cd26e422a370d186f98659383c06721csovant framework. This controls the XPCOM behavior of your object.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li>Implement the XPCOM <a href="#Properties"> properties</a> and methods of your classes as normal.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li>Put the Python source file in the Mozilla <i> components</i> directory.</li>
da97433d5cd26e422a370d186f98659383c06721csovant<p>There are two classes of attributes: those used at runtime to define the object
da97433d5cd26e422a370d186f98659383c06721csovantbehavior and those used at registration time to control object
da97433d5cd26e422a370d186f98659383c06721csovantregistration. Not all objects require registration, thus not all
da97433d5cd26e422a370d186f98659383c06721csovantPython XPCOM objects will have registration-related attributes.</p>
da97433d5cd26e422a370d186f98659383c06721csovant <td width="83%">The interface IDs (IIDs) supported by the component.
da97433d5cd26e422a370d186f98659383c06721csovant For simplicity, this may be either a single IID, or a list of IIDs.
da97433d5cd26e422a370d186f98659383c06721csovant There is no need to specify base interfaces, as all parent interfaces are
da97433d5cd26e422a370d186f98659383c06721csovant automatically supported. Thus, it is never necessary to nominate <i>
da97433d5cd26e422a370d186f98659383c06721csovant nsISupports</i> in the list of interfaces.
da97433d5cd26e422a370d186f98659383c06721csovant <p>This attribute is required. Objects without such an attribute are
da97433d5cd26e422a370d186f98659383c06721csovant deemed unsuitable for use as a XPCOM object.</td>
da97433d5cd26e422a370d186f98659383c06721csovant <td width="83%">The contract ID of the component. Required if the
da97433d5cd26e422a370d186f98659383c06721csovant component requires registration (i.e., exists in the components directory).</td>
da97433d5cd26e422a370d186f98659383c06721csovant <td width="83%">The Class ID (CLSID) of the component, as a string in the
da97433d5cd26e422a370d186f98659383c06721csovant standard "{XXX-XXX-XXX-XXX}" format. Required if the
da97433d5cd26e422a370d186f98659383c06721csovant component requires registration (i.e., exists in the components directory).</td>
da97433d5cd26e422a370d186f98659383c06721csovant <td width="83%">Nominates a function that is called at registration
da97433d5cd26e422a370d186f98659383c06721csovant time. The default is for no extra function to be called. This can
da97433d5cd26e422a370d186f98659383c06721csovant be useful if a component has special registration requirements and needs
da97433d5cd26e422a370d186f98659383c06721csovant to hook into the registration process.</td>
da97433d5cd26e422a370d186f98659383c06721csovant <td width="83%">The description of the XPCOM object. This may be used by
da97433d5cd26e422a370d186f98659383c06721csovant browsers or other such objects. If not specified, the contract ID
da97433d5cd26e422a370d186f98659383c06721csovant is used.</td>
da97433d5cd26e422a370d186f98659383c06721csovant<p>A Python class can support XPCOM properties in one of two ways. Either
da97433d5cd26e422a370d186f98659383c06721csovanta standard Python property of the same name can exist - our sample
da97433d5cd26e422a370d186f98659383c06721csovantcomponent demonstrates this with the <i>boolean_value</i> property.
da97433d5cd26e422a370d186f98659383c06721csovantAlternatively, the class can provide the <i>get_propertyName(self)</i> and <i>set_propertyName(self,
da97433d5cd26e422a370d186f98659383c06721csovantvalue)</i> functions (with <i>propertyName</i> changed to the appropriate value for the
da97433d5cd26e422a370d186f98659383c06721csovantproperty), and these functions will be called instead.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<h4>Example: The Python XPCOM Test Component</h4>
da97433d5cd26e422a370d186f98659383c06721csovant<p>As an example, examine the Python XPCOM Test Component. This
da97433d5cd26e422a370d186f98659383c06721csovantcode can be found in <i>py_test_component.py</i>.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<pre>from xpcom import components
da97433d5cd26e422a370d186f98659383c06721csovantclass PythonTestComponent:
da97433d5cd26e422a370d186f98659383c06721csovant _com_interfaces_ = components.interfaces.nsIPythonTestInterface
da97433d5cd26e422a370d186f98659383c06721csovant _reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}"
da97433d5cd26e422a370d186f98659383c06721csovant _reg_contractid_ = "Python.TestComponent"
da97433d5cd26e422a370d186f98659383c06721csovant def __init__(self):
da97433d5cd26e422a370d186f98659383c06721csovant def do_boolean(self, p1, p2):
da97433d5cd26e422a370d186f98659383c06721csovant ret = p1 ^ p2
da97433d5cd26e422a370d186f98659383c06721csovant return ret, not ret, ret
da97433d5cd26e422a370d186f98659383c06721csovant<p><b>Note:</b> This component only specifies the mandatory attributes - <i>_com_interfaces</i>,
da97433d5cd26e422a370d186f98659383c06721csovant<p>This sample code demonstrates supporting the <i>boolean_value</i> attribute,
da97433d5cd26e422a370d186f98659383c06721csovantsupported implicitly, as it is defined in the IDL and exists as a real Python
da97433d5cd26e422a370d186f98659383c06721csovantattribute of that name, and a method called <i>do_boolean</i>.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<p> The xpcom/xpt.py script is a useful script that can generate the skeleton of a class for
da97433d5cd26e422a370d186f98659383c06721csovantany XPCOM interface. Just specify the interface name on the command-line,
da97433d5cd26e422a370d186f98659383c06721csovantand paste the output into your source file.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<p>This is the output of running this program over the <i>nsISample</i>
da97433d5cd26e422a370d186f98659383c06721csovantinterface (i.e., assuming we wanted to implement a component that supported this
da97433d5cd26e422a370d186f98659383c06721csovantinterface):</p>
da97433d5cd26e422a370d186f98659383c06721csovant<pre>class nsISample:
da97433d5cd26e422a370d186f98659383c06721csovant _com_interfaces_ = xpcom.components.interfaces.nsISample
da97433d5cd26e422a370d186f98659383c06721csovant # If this object needs to be registered, the following 2 are also needed.
da97433d5cd26e422a370d186f98659383c06721csovant # _reg_clsid_ = {a new clsid generated for this object}
da97433d5cd26e422a370d186f98659383c06721csovant # _reg_contractid_ = "The.Object.Name"
da97433d5cd26e422a370d186f98659383c06721csovant def get_value( self ):
da97433d5cd26e422a370d186f98659383c06721csovant # Result: string
da97433d5cd26e422a370d186f98659383c06721csovant def set_value( self, param0 ):
da97433d5cd26e422a370d186f98659383c06721csovant # Result: void - None
da97433d5cd26e422a370d186f98659383c06721csovant # In: param0: string
da97433d5cd26e422a370d186f98659383c06721csovant def writeValue( self, param0 ):
da97433d5cd26e422a370d186f98659383c06721csovant # Result: void - None
da97433d5cd26e422a370d186f98659383c06721csovant # In: param0: string
da97433d5cd26e422a370d186f98659383c06721csovant def poke( self, param0 ):
da97433d5cd26e422a370d186f98659383c06721csovant # Result: void - None
da97433d5cd26e422a370d186f98659383c06721csovant # In: param0: string
da97433d5cd26e422a370d186f98659383c06721csovant<p><b>Note:</b> The types of the parameters and the function itself are included in
da97433d5cd26e422a370d186f98659383c06721csovantthe comments. You need to implement the functions
da97433d5cd26e422a370d186f98659383c06721csovantthemselves. Another advantage of this script is that the <a href="#HiddenParams">hidden
da97433d5cd26e422a370d186f98659383c06721csovantparameters</a> are handled for you; the comments indicate when parameters
da97433d5cd26e422a370d186f98659383c06721csovanthave been hidden.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<h2><a name="Parameters">Parameters and Types</a></h2>
da97433d5cd26e422a370d186f98659383c06721csovant<p>This section briefly describes the XPCOM type support in
da97433d5cd26e422a370d186f98659383c06721csovant<p>All XPCOM interfaces define parameters of a specific type. There is
da97433d5cd26e422a370d186f98659383c06721csovantcurrently no concept of a variant, or union of all types. Thus, the
da97433d5cd26e422a370d186f98659383c06721csovantconversion rules are very straightforward, and generally surprise free: for
da97433d5cd26e422a370d186f98659383c06721csovantany given XPCOM method, there is only one possible type for a given parameter.</p>
da97433d5cd26e422a370d186f98659383c06721csovant <li>All numeric types will attempt to be coerced to the correct type.
da97433d5cd26e422a370d186f98659383c06721csovant Thus, you can pass a Python float to an XPCOM method expecting an integer,
da97433d5cd26e422a370d186f98659383c06721csovant or vice-versa. Specifically, when an integer is required, you can pass
da97433d5cd26e422a370d186f98659383c06721csovant any Python object for which <i>int()</i> would succeed; for a Python float,
da97433d5cd26e422a370d186f98659383c06721csovant any object for which <i>float()</i> would succeed is acceptable. This
da97433d5cd26e422a370d186f98659383c06721csovant means that you can pass a Python string object as an integer, as long as the
da97433d5cd26e422a370d186f98659383c06721csovant string was holding a valid integer.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li>Strings and Unicode objects are interchangeable, but no other automatic
da97433d5cd26e422a370d186f98659383c06721csovant string conversions are performed. Thus, you can not pass an integer
da97433d5cd26e422a370d186f98659383c06721csovant where a string is expected, even though the reverse is true.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li>Any sequence object can be passed as an array. List objects are
da97433d5cd26e422a370d186f98659383c06721csovant always returned for arrays.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li>Any Python instance suitable for use as a XPCOM object (i.e., with the
da97433d5cd26e422a370d186f98659383c06721csovant <a href="#Implementing">necessary annotations</a>) can be
da97433d5cd26e422a370d186f98659383c06721csovant passed as a XPCOM object. No special wrapping step is needed to turn a
da97433d5cd26e422a370d186f98659383c06721csovant Python instance into a XPCOM object. Note you must pass a class <i>instance</i>,
da97433d5cd26e422a370d186f98659383c06721csovant not the class itself.</li>
da97433d5cd26e422a370d186f98659383c06721csovant <li><a name="HiddenParams">Many XPCOM <b> method signatures</b> specify
da97433d5cd26e422a370d186f98659383c06721csovant "count" or "size" parameters. For example, every
da97433d5cd26e422a370d186f98659383c06721csovant time an array is passed via XPCOM, the method signature will always specify
da97433d5cd26e422a370d186f98659383c06721csovant an integer that holds the count of the array. These parameters are
da97433d5cd26e422a370d186f98659383c06721csovant always hidden in Python. As the size param can be implied from the
da97433d5cd26e422a370d186f98659383c06721csovant length of the Python sequence passed, the Python programmer need never pass
da97433d5cd26e422a370d186f98659383c06721csovant these parameters; in contrast, JavaScript requires these redundant parameters.</a></li>
da97433d5cd26e422a370d186f98659383c06721csovant<p>Most people can ignore this information - Python XPCOM objects just
da97433d5cd26e422a370d186f98659383c06721csovantwork. However, if you are familiar with xpcom from C++ and the concept of <i>QueryInterface</i>,
da97433d5cd26e422a370d186f98659383c06721csovantyou may like to read this.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<p>Most components support the concept of "interface
da97433d5cd26e422a370d186f98659383c06721csovantflattening". Such objects can report the interfaces they support,
da97433d5cd26e422a370d186f98659383c06721csovantallowing languages such as Python and Javascript avoid using <i>QueryInterface</i>.
da97433d5cd26e422a370d186f98659383c06721csovantWhen you are using an XPCOM object from Python, you can just call methods and
da97433d5cd26e422a370d186f98659383c06721csovantreference properties without regard for the interface that implements it.</p>
da97433d5cd26e422a370d186f98659383c06721csovant<p>When multiple interfaces share the same method or property name, you can use
da97433d5cd26e422a370d186f98659383c06721csovantthe name of the interface as a differentiator. Thus, <i>ob.nsIFoo.close()</i>
da97433d5cd26e422a370d186f98659383c06721csovantwill call close on <i>ob</i>'s <i>nsIFoo</i> interface, while <i>ob.nsIBar.close()</i>
da97433d5cd26e422a370d186f98659383c06721csovantwill use the <i>nsIBar</i> interface. <i>ob.close()</i> is not defined.</p>