зеркало из https://github.com/mozilla/pjs.git
136 строки
7.2 KiB
HTML
136 строки
7.2 KiB
HTML
<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 Advanced Topics</title>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1>Python XPCOM Advanced Topics</h1>
|
|
|
|
<p>This document contains a series of tidbits that don't fit
|
|
anywhere else. As the Python XPCOM Package documentation matures, most of
|
|
these topics will have another home.</p>
|
|
|
|
<h2>XPCOM Services</h2>
|
|
<p>An XPCOM service is simply a singleton registered by name. Python has
|
|
full support for both using and implementing XPCOM services. To use a
|
|
service, use <i>xpcom.components.services</i> just like the JavaScript
|
|
counterpart. There is nothing special about implementing a service in
|
|
Python; see the standard XPCOM documentation on services for more information.</p>
|
|
|
|
<h2>nsISupports Primitives.</h2>
|
|
|
|
<p>There is a set of interfaces described in <i>nsISupportsPrimitives.idl</i>, which I
|
|
term collectively the <i>nsISupports Primitives Interfaces</i>. These
|
|
are a set of interfaces a component can support to allow automatic conversion to
|
|
and from many basic types. For example, an interface can define that it
|
|
supports the <i>nsISupportsString</i> interface, and this could be used by any
|
|
program that wishes to get a string representation of the object. If an
|
|
interface wishes to expose itself as a "boolean value", it may choose
|
|
to support the <i>nsISupportsPRBool</i> interface.</p>
|
|
<p>When you call an XPCOM object (i.e., you have an XPCOM interface you are
|
|
calling), you can use
|
|
the builtin functions <i>str()</i>, <i>int()</i>, <i>long()</i> etc., on the
|
|
object<i>.</i> In the
|
|
case of <i>str()</i>, if the object does not support the <i>nsISupportsString</i>
|
|
or <i>nsISupportsWString</i> interfaces, the default string <i>str()</i> for the
|
|
object will be returned (i.e., what is normally returned for most XPCOM objects -
|
|
support for these interface is not very common!). In the case of the numeric functions, a <i>ValueError</i>
|
|
exception 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
|
|
of these interfaces:</p>
|
|
<ul>
|
|
<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
|
|
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>nsISupportsString</i>
|
|
and <i>nsISupportsWString</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>
|
|
</ul>
|
|
<blockquote>
|
|
<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>nsISupportsString</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>
|
|
|
|
</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 "scriptable", 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. 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. 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. 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>
|
|
<h2>Policies</h2>
|
|
<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>
|
|
|
|
</body>
|
|
|
|
</html>
|