Creating Applications with Mozilla 已经包含了一个教程用于编写简单的基于JavaScript和C++(实现nsISimple
接口)的组件,本文阐述如何通过Python语言使用PyXPCOM创建相同的组件。
(Note that some details may be missing)
准备
如果你还没有PyXPCOM的二进制文件,请参考Building PyXPCOM以编译PyXPCOM的二进制文件。
如果你想在通常的Python可执行环境中使用PyXPCOM,你需要告诉Python在哪里可以找到PyXPCOM库。或许最好的办法就是在应用中设置变量PYTHONPATH指向'bin/python'目录。当然这在你的组件通过Mozilla被加载时是没有必要的因为Python加载器会完成sys.path的修改。
然后你可以
import xpcom
在任何Python模块里(大多数情况下是在你的组件中)。
定义接口
创建一个名为"nslPySimple.idl"的文件用于定义接口:
#include "nsISupports.idl" [scriptable, uuid(2b324e9d-a322-44a7-bd6e-0d8c83d94883)] interface nsIPySimple : nsISupports { attribute string yourName; void write( ); void change(in string aValue); };
这与在这里使用nsISimple是相同的。理论上由于多个组件可以共享一个接口,因此使用了相同的接口文件。
需要特别留意一下,Python和JavaScript都是弱类型的语言,所以比较容易从一个到另一个传递信息。
Note: There are exceptions; see this discussion for information on the use of string
and wstring
for unicode transfer. See here for info on describing interfaces, and on which types can be used.
注册接口
在"components"目录中执行如下命令:
../xpidl -m typelib -w -v -I /usr/share/idl/mozilla/ nsIPySimple.idl
在Windows中你必须要将idl目录指定成Mozilla构建目录。例如:
xpidl.exe -m typelib -w -v -I C:\source\mozilla\obj-i686-pc-mingw32\dist\idl foo.idl
然后xpidl将创建nslPySimple.xpt文件并正确放置到目录中(如'components'目录)。
实现组件
不同于C++,PyXPCOM为你做了很多事情。
创建了一个名为"py_simple.py"的文件用于实际的代码(同样是在'components'目录中)。
from xpcom import components, verbose class PySimple: #PythonTestComponent _com_interfaces_ = components.interfaces.nsIPySimple _reg_clsid_ = "{c456ceb5-f142-40a8-becc-764911bc8ca5}" _reg_contractid_ = "@mozilla.org/PySimple;1" def __init__(self): self.yourName = "a default name" # or mName ? def __del__(self): if verbose: print "PySimple: __del__ method called - object is destructing" def write(self): print self.yourName def change(self, newName): self.yourName = newName
接口下来是注册组件;这个步骤相同于其它组件,但在Python组件不可用的状态下会失败。
为了注册组件,你需要在bin目录中
touch
(创建)一个隐藏文件.autoreg,或者是删除xpti.dat文件。之后在下一次Mozilla
启动时会重新构建组件的索引,包括任何'components'目录下新的组件。这对接下来通过命令行启动Mozilla以查看组件是否注册成功来讲非常有帮助。
生成实现模板
xpcom.xpt模块被用于内部以处理类型信息,但它有一个非常好的功能,可以为任何接口的Python实现生成一个模板。
以脚本的方式执行这个文件并且以接口名字作为参数。例如:
% cd c:\mozilla\bin\python\xpcom % python xpt.py nsISample 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
正如你所见到的,输出的是有效的Python代码,并带有每个方法的基本的方法签名和有效的注释信息。
测试
为了看到执行结果,你需要从命令行启动Firefox,因为那才是执行结果被打印出来的地方。
外部连接
- Creating XPCOM components, on which this short tutorial is based.
- A three-part tutorial on ibm developerWorks:
- Getting to know PyXPCOM - info on building PyXPCOM (and maybe Mozilla) to get it to work.
- Getting started with PyXPCOM, part 2 - accessing xpcom from Python.
- Getting started with PyXPCOM, part 3 - Creating your own components. The problem with this one is that the sample code they give is slightly broken (it ends with a "retu" which shouldn't be there. I haven't tried it, but it looks like nothing is missing, so getting rid of the "retu" should make it work fine.).