First checkin of the Python XPCOM bindings.
git-svn-id: svn://10.0.0.236/trunk@87331 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
240
mozilla/extensions/python/xpcom/doc/tutorial.html
Normal file
240
mozilla/extensions/python/xpcom/doc/tutorial.html
Normal file
@@ -0,0 +1,240 @@
|
||||
<html>
|
||||
<!-- Copyright (c) 2000-2001 ActiveState Tool Corporation.
|
||||
See the file LICENSE.txt for licensing information. -->
|
||||
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Python XPCOM Package Tutorial</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Python XPCOM Package Tutorial</h1>
|
||||
<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>,
|
||||
and have experience both using and implementing XPCOM objects in some other
|
||||
language (e.g., C++ or JavaScript). We <b><i>do not</i></b> attempt to
|
||||
provide a tutorial to XPCOM or Python itself, only to using Python <i>and</i>
|
||||
XPCOM.</p>
|
||||
<p>This tutorial contains the following sections:</p>
|
||||
<ul>
|
||||
<li><a href="#Using">Using XPCOM Objects and Interfaces</a> - when you wish to
|
||||
<i>use</i> a component written by anyone else in any XPCOM supported
|
||||
language.</li>
|
||||
<li><a href="#Implementing">Implementing XPCOM Objects and Interfaces</a> -
|
||||
when you wish to implement a component for use by anyone else in any xpcom
|
||||
supported language.</li>
|
||||
<li><a href="#Parameters">Parameters and Types</a> - useful information
|
||||
regarding how Python translates XPCOM types, and handles byref parameters.</li>
|
||||
</ul>
|
||||
<p>For anything not covered here, try the <a href="advanced.html">advanced
|
||||
documentation</a>, and if that fails, use the source, Luke!</p>
|
||||
<h2><a name="Using">Using XPCOM object and interfaces.</a></h2>
|
||||
<p>The techniques for using XPCOM in Python have been borrowed from JavaScript -
|
||||
thus, the model described here should be quite familiar to existing JavaScript
|
||||
XPCOM programmers.</p>
|
||||
<h3>xpcom.components module</h3>
|
||||
<p>When using an XPCOM object, the primary module used is the <u><i>xpcom.components</i></u>
|
||||
module. Using this module, you can get a Python object that supports any
|
||||
scriptable XPCOM interface. Once you have this Python object, you can
|
||||
simply call XPCOM methods on the object, as normal.</p>
|
||||
<p>The <u><i>xpcom.components</i></u> module defines the following public
|
||||
members:</p>
|
||||
<table border="1" width="100%">
|
||||
<tr>
|
||||
<td width="16%"><b>Name</b></td>
|
||||
<td width="84%"><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="16%">classes</td>
|
||||
<td width="84%">A mapping (dictionary-like object) used to get XPCOM
|
||||
"classes". These are indexed by XPCOM contract ID, just
|
||||
like the JavaScript object of the same name.
|
||||
<p>Example:</p>
|
||||
<pre>cls = components.classes["@mozilla.org/sample;1"]
|
||||
ob = cls.createInstance() # Now have an nsISupports</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="16%">interfaces</td>
|
||||
<td width="84%">An object that exposes all XPCOM interface IDs (IIDs).
|
||||
Like the JavaScript object of the same name, this object uses
|
||||
"dot" notation, as demonstrated below.
|
||||
<p>Example:</p>
|
||||
<pre>ob = cls.createInstance(components.interfaces.nsISample)
|
||||
# Now have an nsISample</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>For many people, this is all you need to know. Consider the Mozilla Sample Component. The Mozilla Sample
|
||||
Component has a contract ID of <i>@mozilla.org/sample;1</i>,
|
||||
and implements the <i>nsISample</i> interface.</p>
|
||||
<p>Thus, a complete Python program that uses this component is shown below.</p>
|
||||
<pre>from xpcom import components
|
||||
cls = components.classes["@mozilla.org/sample;1"]
|
||||
ob = cls.createInstance(components.interfaces.nsISample)
|
||||
# nsISample defines a "value" property - let's use it!
|
||||
ob.value = "new value"
|
||||
if ob.value != "new value":
|
||||
print "Eeek - what happened?"</pre>
|
||||
<p>And that is it - a complete Python program that uses XPCOM.</p>
|
||||
<h2><a name="Implementing">Implementing XPCOM Objects and Interfaces.</a></h2>
|
||||
<p>Implementing XPCOM objects is almost as simple as using them. The
|
||||
basic strategy is this:</p>
|
||||
<ol>
|
||||
<li>Create a standard Python source file, with a standard Python class.</li>
|
||||
<li>Add some special <a href="#Attributes"> attributes</a> to your class for use by the Python XPCOM
|
||||
framework. This controls the XPCOM behavior of your object.</li>
|
||||
<li>Implement the XPCOM <a href="#Properties"> properties</a> and methods of your classes as normal.</li>
|
||||
<li>Put the Python source file in the Mozilla <i> components</i> directory.</li>
|
||||
<li>Run <i> regxpcom.</i></li>
|
||||
</ol>
|
||||
<p>Your component is now ready to be used.</p>
|
||||
<h3><a name="Attributes">Attributes</a></h3>
|
||||
<p>There are two classes of attributes: those used at runtime to define the object
|
||||
behavior and those used at registration time to control object
|
||||
registration. Not all objects require registration, thus not all
|
||||
Python XPCOM objects will have registration-related attributes.</p>
|
||||
<table border="1" width="100%">
|
||||
<tr>
|
||||
<td width="17%"><b>Attribute</b></td>
|
||||
<td width="83%"><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_com_interfaces_</td>
|
||||
<td width="83%">The interface IDs (IIDs) supported by the component.
|
||||
For simplicity, this may be either a single IID, or a list of IIDs.
|
||||
There is no need to specify base interfaces, as all parent interfaces are
|
||||
automatically supported. Thus, it is never necessary to nominate <i>
|
||||
nsISupports</i> in the list of interfaces.
|
||||
<p>This attribute is required. Objects without such an attribute are
|
||||
deemed unsuitable for use as a XPCOM object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_contractid_</td>
|
||||
<td width="83%">The contract ID of the component. Required if the
|
||||
component requires registration (i.e., exists in the components directory).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_clsid_</td>
|
||||
<td width="83%">The Class ID (CLSID) of the component, as a string in the
|
||||
standard "{XXX-XXX-XXX-XXX}" format. Required if the
|
||||
component requires registration (i.e., exists in the components directory).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_registrar_</td>
|
||||
<td width="83%">Nominates a function that is called at registration
|
||||
time. The default is for no extra function to be called. This can
|
||||
be useful if a component has special registration requirements and needs
|
||||
to hook into the registration process.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%">_reg_desc_</td>
|
||||
<td width="83%">The description of the XPCOM object. This may be used by
|
||||
browsers or other such objects. If not specified, the contract ID
|
||||
is used.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3><a name="Properties">Properties</a></h3>
|
||||
<p>A Python class can support XPCOM properties in one of two ways. Either
|
||||
a standard Python property of the same name can exist - our sample
|
||||
component demonstrates this with the <i>boolean_value</i> property.
|
||||
Alternatively, the class can provide the <i>get_propertyName(self)</i> and <i>set_propertyName(self,
|
||||
value)</i> functions (with <i>propertyName</i> changed to the appropriate value for the
|
||||
property), and these functions will be called instead.</p>
|
||||
<h4>Example: The Python XPCOM Test Component</h4>
|
||||
<p>As an example, examine the Python XPCOM Test Component. This
|
||||
code can be found in <i>py_test_component.py</i>.</p>
|
||||
<pre>from xpcom import components
|
||||
|
||||
class PythonTestComponent:
|
||||
_com_interfaces_ = components.interfaces.nsIPythonTestInterface
|
||||
_reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}"
|
||||
_reg_contractid_ = "Python.TestComponent"
|
||||
def __init__(self):
|
||||
self.boolean_value = 1
|
||||
...
|
||||
def do_boolean(self, p1, p2):
|
||||
ret = p1 ^ p2
|
||||
return ret, not ret, ret
|
||||
...</pre>
|
||||
<p><b>Note:</b> This component only specifies the mandatory attributes - <i>_com_interfaces</i>,
|
||||
<i>_reg_clsid_</i> and <i>_reg_contractid_</i>.</p>
|
||||
<p>This sample code demonstrates supporting the <i>boolean_value</i> attribute,
|
||||
supported implicitly, as it is defined in the IDL and exists as a real Python
|
||||
attribute of that name, and a method called <i>do_boolean</i>.</p>
|
||||
<h4>Tip: The xpcom/xpt.py Script</h4>
|
||||
<p> The xpcom/xpt.py script is a useful script that can generate the skeleton of a class for
|
||||
any XPCOM interface. Just specify the interface name on the command-line,
|
||||
and paste the output into your source file.</p>
|
||||
<p>This is the output of running this program over the <i>nsISample</i>
|
||||
interface (i.e., assuming we wanted to implement a component that supported this
|
||||
interface):</p>
|
||||
<pre>class nsISample:
|
||||
_com_interfaces_ = xpcom.components.interfaces.nsISample
|
||||
# If this object needs to be registered, the following 2 are also needed.
|
||||
# _reg_clsid_ = {a new clsid generated for this object}
|
||||
# _reg_contractid_ = "The.Object.Name"
|
||||
|
||||
def get_value( self ):
|
||||
# Result: string
|
||||
pass
|
||||
def set_value( self, param0 ):
|
||||
# Result: void - None
|
||||
# In: param0: string
|
||||
pass
|
||||
def writeValue( self, param0 ):
|
||||
# Result: void - None
|
||||
# In: param0: string
|
||||
pass
|
||||
def poke( self, param0 ):
|
||||
# Result: void - None
|
||||
# In: param0: string
|
||||
pass</pre>
|
||||
<p><b>Note:</b> The types of the parameters and the function itself are included in
|
||||
the comments. You need to implement the functions
|
||||
themselves. Another advantage of this script is that the <a href="#HiddenParams">hidden
|
||||
parameters</a> are handled for you; the comments indicate when parameters
|
||||
have been hidden.</p>
|
||||
<h2><a name="Parameters">Parameters and Types</a></h2>
|
||||
<p>This section briefly describes the XPCOM type support in
|
||||
Python.</p>
|
||||
<p>All XPCOM interfaces define parameters of a specific type. There is
|
||||
currently no concept of a variant, or union of all types. Thus, the
|
||||
conversion rules are very straightforward, and generally surprise free: for
|
||||
any given XPCOM method, there is only one possible type for a given parameter.</p>
|
||||
<h3>Type Conversion Rules:</h3>
|
||||
<ul>
|
||||
<li>All numeric types will attempt to be coerced to the correct type.
|
||||
Thus, you can pass a Python float to an XPCOM method expecting an integer,
|
||||
or vice-versa. Specifically, when an integer is required, you can pass
|
||||
any Python object for which <i>int()</i> would succeed; for a Python float,
|
||||
any object for which <i>float()</i> would succeed is acceptable. This
|
||||
means that you can pass a Python string object as an integer, as long as the
|
||||
string was holding a valid integer.</li>
|
||||
<li>Strings and Unicode objects are interchangeable, but no other automatic
|
||||
string conversions are performed. Thus, you can not pass an integer
|
||||
where a string is expected, even though the reverse is true.</li>
|
||||
<li>Any sequence object can be passed as an array. List objects are
|
||||
always returned for arrays.</li>
|
||||
<li>Any Python instance suitable for use as a XPCOM object (i.e., with the
|
||||
<a href="#Implementing">necessary annotations</a>) can be
|
||||
passed as a XPCOM object. No special wrapping step is needed to turn a
|
||||
Python instance into a XPCOM object. Note you must pass a class <i>instance</i>,
|
||||
not the class itself.</li>
|
||||
<li><a name="HiddenParams">Many XPCOM <b> method signatures</b> specify
|
||||
"count" or "size" parameters. For example, every
|
||||
time an array is passed via XPCOM, the method signature will always specify
|
||||
an integer that holds the count of the array. These parameters are
|
||||
always hidden in Python. As the size param can be implied from the
|
||||
length of the Python sequence passed, the Python programmer need never pass
|
||||
these parameters; in contrast, JavaScript requires these redundant parameters.</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user