1335N/A<!-- ***** BEGIN LICENSE BLOCK ***** 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 - 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 - The Original Code is PyXPCOM. 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 - 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. 1335N/A - ***** END LICENSE BLOCK ***** --> 2899N/A<
meta http-
equiv="Content-Type" content="text/html; charset=windows-1252">
2818N/A<
meta name="GENERATOR" content="Microsoft FrontPage 4.0">
2818N/A<
title>Python XPCOM Advanced Topics</
title>
1335N/A<
h1>Python XPCOM Advanced Topics</
h1>
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<
p>An XPCOM service is simply a singleton registered by name. Python has
3936N/Afull support for both using and implementing XPCOM services. To use a
4661N/Acounterpart. There is nothing special about implementing a service in
4661N/APython; see the standard XPCOM documentation on services for more information.</
p>
4661N/A<
p>There is (almost) full support for <
i>nsIVariant</
i>. Any <
i>nsIVariant</
i>
4661N/Aparameters will automatically be translated to and from regular Python objects
4661N/Agiving, in effect, a multi-type parameter. This should be automatic, so
4661N/Athere is not much else to say! 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<
h2>nsISupports Primitives.</
h2>
4661N/Aterm collectively the <
i>nsISupports Primitives Interfaces</
i>. These
1938N/Aare a set of interfaces a component can support to allow automatic conversion to
1938N/Aand from many basic types. 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. If an
1335N/Ainterface wishes to expose itself as a "boolean value", 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
4337N/Athe builtin functions <
i>str()</
i>, <
i>int()</
i>, <
i>long()</
i> etc., on 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!). 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. <
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
"real" object, rather than what the object wants you to see!</
p>
<
p>When you implement an XPCOM object, you have two choices for implementation
<
li>You can explicitly handle these interfaces like any other interface.
In this case, you have full control. 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
<
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. 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>
<
p>This allows for an interesting feature that would not normally be
possible. Consider Python code that does a <
i>str()</
i> on an XPCOM
interface, and where the XPCOM interface itself is implemented in Python and
provides a <
i>__str__</
i> method. The <
i>str()</
i> on the original
interface queries for the <
i>nsISupportsCString</
i> interface. 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>
<
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 "scriptable", you should avoided using it in interfaces
<
p>When you use <
i>nsISimpleEnumerator</
i> from Python, the following enhancements
<
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. This
prevents the manual <
i>QueryInterface()</
i> generally required from other
<
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>
<
p><
i>nsIEnumerator</
i> has similar enhancements.</
p>
can be used. You can pass a standard Python sequence (list, etc), and it
will be correctly wrapped in an <
i>nsISimpleEnumerator</
i> interface.</
p>
<
p>The Python XPCOM package provides an <
i>
xpcom.file</
i> module. This implements
a Python-like file object on top of the
XPCOM/
Mozilla stream interfaces.
When run from within the Mozilla environment, this allows you to open almost any
URL supported by Mozilla (including "chrome://" 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. 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. Critically, the framework provides no mechanism
for breaking these rules.</
p>
<
p>The Python XPCOM framework has the concept of "policies" that
define how XPCOM semantics are mapped to Python objects. It is the policy
that implements delegation of <
i> QueryInterface()</
i>, translates property
references into direct property references, and failing that, "get_name"
and "set_name" 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>