advanced.html revision 16a8d09569a2ebd598cef72fa605be6fb4563607
1335N/A<html>
1335N/A<!-- ***** BEGIN LICENSE BLOCK *****
1335N/A - Version: MPL 1.1/GPL 2.0/LGPL 2.1
1335N/A -
1335N/A - The contents of this file are subject to the Mozilla Public License Version
1335N/A - 1.1 (the "License"); you may not use this file except in compliance with
1335N/A - the License. You may obtain a copy of the License at
1335N/A - http://www.mozilla.org/MPL/
1335N/A -
1335N/A - Software distributed under the License is distributed on an "AS IS" basis,
1335N/A - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1335N/A - for the specific language governing rights and limitations under the
1335N/A - License.
1335N/A -
1335N/A - The Original Code is PyXPCOM.
1335N/A -
1335N/A - The Initial Developer of the Original Code is
1335N/A - ActiveState Tool Corporation.
1335N/A - Portions created by the Initial Developer are Copyright (C) 2000-2001
1335N/A - the Initial Developer. All Rights Reserved.
1335N/A -
1335N/A - Contributor(s):
3817N/A -
1335N/A - Alternatively, the contents of this file may be used under the terms of
1335N/A - either the GNU General Public License Version 2 or later (the "GPL"), or
1335N/A - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1335N/A - in which case the provisions of the GPL or the LGPL are applicable instead
1335N/A - of those above. If you wish to allow use of your version of this file only
1335N/A - under the terms of either the GPL or the LGPL, and not to allow others to
1335N/A - use your version of this file under the terms of the MPL, indicate your
1335N/A - decision by deleting the provisions above and replace them with the notice
1335N/A - and other provisions required by the LGPL or the GPL. If you do not delete
1335N/A - the provisions above, a recipient may use your version of this file under
1335N/A - the terms of any one of the MPL, the GPL or the LGPL.
4845N/A -
1335N/A - ***** END LICENSE BLOCK ***** -->
1335N/A
2899N/A<head>
2899N/A<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
2818N/A<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
3936N/A<meta name="ProgId" content="FrontPage.Editor.Document">
2818N/A<title>Python XPCOM Advanced Topics</title>
3817N/A</head>
3817N/A
3817N/A<body>
1335N/A
1335N/A<h1>Python XPCOM Advanced Topics</h1>
1335N/A
1335N/A<p>This document contains a series of tidbits that don't fit
1335N/Aanywhere else. As the Python XPCOM Package documentation matures, most of
3936N/Athese topics will have another home.</p>
3936N/A
3936N/A<h2>XPCOM Services</h2>
3936N/A<p>An XPCOM service is simply a singleton registered by name.&nbsp; Python has
3936N/Afull support for both using and implementing XPCOM services.&nbsp; To use a
4661N/Aservice, use <i>xpcom.components.services</i> just like the JavaScript
4661N/Acounterpart.&nbsp; There is nothing special about implementing a service in
4661N/APython; see the standard XPCOM documentation on services for more information.</p>
4661N/A
4661N/A<h2>nsIVariant</h2>
4661N/A
4661N/A<p>There is (almost) full support for <i>nsIVariant</i>.&nbsp; Any <i>nsIVariant</i>
4661N/Aparameters will automatically be translated to and from regular Python objects
4661N/Agiving, in effect, a multi-type parameter.&nbsp; This should be automatic, so
4661N/Athere is not much else to say!&nbsp; Note that if you really want, you can
4661N/Acreate and pass your own <i>nsIVariant</i> object instead of a regular Python
4661N/Aobject, thereby allowing explicit control over the type of variant created.</p>
4661N/A
4661N/A<h2>nsISupports Primitives.</h2>
4661N/A
4661N/A<p>There is a set of interfaces described in <i>nsISupportsPrimitives.idl</i>, which I
4661N/Aterm collectively the <i>nsISupports Primitives Interfaces</i>.&nbsp; These
1938N/Aare a set of interfaces a component can support to allow automatic conversion to
1938N/Aand from many basic types.&nbsp; For example, an interface can define that it
1335N/Asupports the <i>nsISupportsCString</i> interface, and this could be used by any
1335N/Aprogram that wishes to get a string representation of the object.&nbsp; If an
1335N/Ainterface wishes to expose itself as a &quot;boolean value&quot;, it may choose
1335N/Ato support the <i>nsISupportsPRBool</i> interface.</p>
4661N/A<p>When you call an XPCOM object (i.e., you have an XPCOM interface you are
1335N/Acalling), you can use
4337N/Athe builtin functions <i>str()</i>, <i>int()</i>, <i>long()</i> etc., on the
4337N/Aobject<i>.</i>&nbsp; In the
3817N/Acase of <i>str()</i>, if the object does not support the <i>nsISupportsCString</i>
3817N/Aor <i>nsISupportsString</i> interfaces, the default string <i>str()</i> for the
3817N/Aobject will be returned (i.e., what is normally returned for most XPCOM objects -
3817N/Asupport for these interface is not very common!).&nbsp; In the case of the numeric functions, a <i>ValueError</i>
4661N/Aexception will be raised if the objects do not support any interface that can be
used for the conversion.&nbsp;<i>ValueError</i> is used instead of <i>TypeError</i>,
as the type itself (i.e., an XPCOM object) can sometimes be used in this context -
hence it is the specific <i>value</i> of the object that is the problem.</p>
<p>The use of <i>repr()</i> on an XPCOM interface object prevents support
attempts for these interfaces, and allows you to see the
&quot;real&quot; object, rather than what the object wants you to see!</p>
<p>When you implement an XPCOM object, you have two choices for implementation
of these interfaces:</p>
<ul>
<li>You can explicitly handle these interfaces like any other interface.&nbsp;
In this case, you have full control.&nbsp; However, if you
implement only one of these standard interfaces, then you are only
overriding the default behavior for that specific interface - all other
interfaces not explicitly listed in your class will still get the behavior
described below.<br>
</li>
<li>If your class does not define support for these interfaces, the framework
will use standard Python class semantics to implement them - i.e., if your
class provides a <i>__str__</i> method, it will be used to implement <i>nsISupportsCString</i>
and <i>nsISupportsString</i>, if you provide <i>__int__</i>, <i>__long__</i>,
<i>__float__</i> etc., methods, they will be used to implement the numeric
interfaces.&nbsp; If your class defines no such special methods, then the <i>
QueryInterface()</i> for those interfaces fails (rather than the QI succeeding
and the operation to fetch the data failing).</li>
</ul>
<blockquote>
<p>This allows for an interesting feature that would not normally be
possible.&nbsp; Consider Python code that does a <i>str()</i> on an&nbsp; XPCOM
interface, and where the XPCOM interface itself is implemented in Python and
provides a <i>__str__</i> method.&nbsp; The <i>str()</i> on the original
interface queries for the <i>nsISupportsCString</i> interface.&nbsp; The
Python implemented object responds to this interface and delegates to the <i>__str__</i>
method. At the end of all this, <i>str()</i> returns the same result
as if the objects were native Python objects with no XPCOM layer in between.</p>
</blockquote>
<h2>Enumerators</h2>
<p>The primary enumerator used by XPCOM is <i>nsISimpleEnumerator</i>.
Although the Python XPCOM package has full support for <i>nsIEnumerator</i>,
since this interface is not &quot;scriptable&quot;, you should avoided using it in interfaces
you design.</p>
<p>When you use <i>nsISimpleEnumerator</i> from Python, the following enhancements
are available:</p>
<ul>
<li>The <i>GetNext()</i> method takes an optional IID as a parameter. If
this is specified, the returned object will be of this interface.&nbsp; This
prevents the manual <i>QueryInterface()</i> generally required from other
languages.</li>
<li>There is a <i>FetchBlock(num, [iid])</i> method, which fetches the
specified number of elements in one operation and returns a Python
list. This can be useful for large enumerator sets, so the loop
iterating the elements runs at full C++ speed.</li>
</ul>
<p><i>nsIEnumerator</i> has similar enhancements.</p>
<p>When implementing a Python XPCOM object, the Python class <i>xpcom.server.enumerator.SimpleEnumerator()</i>
can be used.&nbsp; You can pass a standard Python sequence (list, etc), and it
will be correctly wrapped in an <i>nsISimpleEnumerator</i> interface.</p>
<h2>Files</h2>
<p>The Python XPCOM package provides an <i> xpcom.file</i> module.&nbsp; This implements
a Python-like file object on top of the XPCOM/Mozilla stream interfaces.&nbsp;
When run from within the Mozilla environment, this allows you to open almost any
URL supported by Mozilla (including &quot;chrome://&quot; etc.,).</p>
<p>See this module for more information, including test code.</p>
<h2>XPCOM Object Identity</h2>
<p>XPCOM has defined rules for object identity and for how objects must behave
in their <i> QueryInterface()</i> implementations.&nbsp; The Python XPCOM framework
manages this for you; your code can return new Python instances etc., when
responding to new interfaces, and the framework itself will ensure the XPCOM
semantics are followed.&nbsp; Critically, the framework provides no mechanism
for breaking these rules.</p>
<h2>Policies</h2>
<p>The Python XPCOM framework has the concept of &quot;policies&quot; that
define how XPCOM semantics are mapped to Python objects.&nbsp; It is the policy
that implements delegation of <i> QueryInterface()</i>, translates property
references into direct property references, and failing that, &quot;get_name&quot;
and &quot;set_name&quot; calls, decides how to handle exceptions in the
component, and so on.</p>
<p>The default policy is very flexible and suitable for most purposes.
Indeed, the Komodo project has never had to implement a custom policy.
However, you should be aware the feature exists should you wish to do some
bizarre things, such as using Python as a bridge between XPCOM and some other
component technology.</p>
</body>
</html>