您的位置:首页 > 其它

基于Mozilla平台的扩展开发(续)----XPCOM组件篇

2008-04-25 22:50 411 查看
源代码下载:HelloWorld示例.rar

在《浅谈基于Mozilla ThunderBird的扩展开发》这篇入门文章中简单介绍了基于Mozllia平台进行扩展开发的基础知识,但仍然欠缺最为重要的一种武器---没错,XPCOM!这篇文章就是为它准备的。
XPCOM[/b]是什么?[/b][/b]
这个问题不多做解释了,相信XPCOM对于了解COM技术的人来说很快就可以上手开发了,下列是Mozilla官方给出的一些XPCOM知识的入门资源:

Creating XPCOM Components written by Doug Turner and Ian Oeschger that introduces XPCOM and illustrates how to create XPCOM components for Gecko-based applications.

An introduction to XPCOM on IBM's website by Rick Parrish.

Presentation: Introduction To XPCOM, Alec Flett (Feb 4, 2002)

Presentation: The XPCOM Library, Alec Flett (Feb 11, 2002)

Standalone XPCOM : Document on building xpcom standalone.

个人尤其推荐IBM developerworks上那5篇文章。
[/b]使用已有的[/b]XPCOM[/b]
[/b]XPCOM的使用十分简单,Mozilla平台已经为我们提供了许多功能强大的XPCOM组件了,如果你需要某方面功能的组件,请先看看Mozilla平台下是不是已经有对应的了,别再“自己造轮子了“。
关于这方面也不打算再多说了,有兴趣的朋友可以阅读IBM developerworks下面这篇文章,《实战 Firefox 扩展开发》,相信通过这样一个图片批量下载工具的开发,就会对于Mozilla平台下已有的XPCOM组件的使用有所了解的。

So,what's next?

没错,自己如何开发XPCOM组件并在扩展中使用。网上对于这方面的资料不是很多,而且没有特别完整的示例,这就是我写这篇文章的目的所在,通过一个简单的XPCOM组件的开发全过程,展示XPCOM组件的内部细节。

项目目标:

组件要实现的功能非常简单,就只提供一个做加法的接口供客户调用。
long Add(in long a, in long b);
然后在扩展中调用这个加法接口。

准备工作[/b][/b]
[/b]
0,按照《浅谈基于Mozilla ThunderBird的扩展开发》这篇文章建立起开发扩展的基本环境。
1、下载Gecko SDK
http://ftp.mozilla.org/pub/mozilla.org/mozilla/releases/mozilla1.8b1/gecko-sdk-i586-pc-msvc-1.8b1.zip ,我们需要使用它来对IDL定义进行解释。
2、创建GUID
使用微软的的guidgen 生成GUID,例如b7b04070-45fc -4635- b219-7a172f806bee
4,从C:/mozilla-build/moztools-180compat/bin下拷贝libIDL-0.6.dll,glib-1.2.dll到/gecko-sdk-i586-pc-msvc-1.8b1/gecko-sdk/bin下,否则运行xpidl会报错.

开发XPCOM组件

1,创建接口文件定义


#include "nsISupports.idl"


[scriptable, uuid(b7b04070-45fc -4635- b219-7a172f806bee)]


interface IMyComponent : nsISupports






{


long Add(in long a, in long b);


};



2、使用Gecko SDK 的xpidl.exe
进入xpidl所在目录,在CMD中输入命令


xpidl -m header -I ../idl IMyComponent.idl(这里应该是IDL定义文件的实际路径)


xpidl -m typelib -I ../idl IMyComponent.idl



如果上面执行有问题的话,可以将


/gecko-sdk-i586-pc-msvc-1.8b1/gecko-sdk/bin;/gecko-sdk-i586-pc-msvc-1.8b1/gecko-sdk/idl;/gecko-sdk-i586-pc-msvc-1.8b1/gecko-sdk/include;
加入到环境变量的PATH里面去。
如果上述命令执行通过,在/gecko-sdk-i586-pc-msvc-1.8b1/gecko-sdk/bin就会得到IMyComponent.h,IMyComponent.xpt 这2个文件。
2、创建新文件
根据IMyComponent.h创建文件MyComponent.h,MyComponent.cpp,MyComponentModule.cpp。




/**//* MyComponent.h*/




#pragma once




#ifndef _MY_COMPONENT_H_


#define _MY_COMPONENT_H_




#include "IMyComponent.h"


#define MY_COMPONENT_CONTRACTID "@mydomain.com/XPCOMSample/MyComponent;1"


#define MY_COMPONENT_CLASSNAME "A Simple XPCOM Sample"


#define MY_COMPONENT_CID {0xb7b04070, 0x45fc, 0x4635,{ 0xb2, 0x19, 0x7a, 0x17, 0x2f, 0x80, 0x6b, 0xee } }






class MyComponent:public IMyComponent






{


public:


NS_DECL_ISUPPORTS


NS_DECL_IMYCOMPONENT


MyComponent(void);


~MyComponent(void);


};


#endif








/**//* MyComponent.cpp*/


#include "StdAfx.h"


#include "MyComponent.h"




NS_IMPL_ISUPPORTS1(MyComponent, IMyComponent)




MyComponent::MyComponent(void)






{


}




MyComponent::~MyComponent(void)






{


}




NS_IMETHODIMP MyComponent::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)






{


*_retval = a + b;


return NS_OK;


}






/**//* MyComponentModule.cpp*/


#include "StdAfx.h"


#include "nsIGenericFactory.h"


#include "MyComponent.h"




NS_GENERIC_FACTORY_CONSTRUCTOR(MyComponent)




static nsModuleComponentInfo components[] =






{






{


MY_COMPONENT_CLASSNAME,


MY_COMPONENT_CID,


MY_COMPONENT_CONTRACTID,


MyComponentConstructor,


}


};




NS_IMPL_NSGETMODULE("MyComponentsModule", components)



编译XPCOM组件

1、创建工程
使用VC2005,创建新的DLL工程,将IMyComponent.h, MyComponent.h,MyComponent.cpp,MyComponentModule.cpp添加到工程中。

2、工程配置


1)c/c++ GeneralAdditional Include Directories 中设置为/gecko-sdk-i586-pc-msvc-1.8b1/gecko-sdk/include


2) c/c++Preprocessor Preprocessor Definitions中加入MYCOMPONENT_EXPORTS,XPCOM_GLUE


3)c/c++Code GenerationRuntime Library中设置为Multi-threaded DLL (/MD)


,这里非常重要,否则编译会报错的!!。


4)LinkerAdditional Liberary Directoryse设置为/gecko-sdk-i586-pc-msvc-1.8b1/gecko-sdk/lib


5)Linker Additional Depenendies加入nspr4.lib plds4.lib plc4.lib xpcomglue.lib



3、编译生成MyComponent.dll。

在扩展中使用[/b]XPCOM[/b]组件[/b][/b]

对《浅谈基于Mozilla ThunderBird的扩展开发》中的helloworld项目进行修改,加入一个文件夹components和一个安装文件install.js。



关于这两个东西具体的含义这里就不多做介绍了,简单点说,intall.js就是把XPCOM组件注册到Mozilla平台中去,就类似于Windows的注册表一样,从而可以使用组件。

1)Install.js的内容:


// Install script for helloworld




var err;


const APP_VERSION="0.0.0.1";//版本号




//初始化安装


err = initInstall("helloworld"+APP_VERSION, // name for install UI


"/helloworld", // registered name


APP_VERSION); // package version


if(err!=0)






{//安装出错,取消安装


cancelInstall(err);


}




//标准目录


var fProgram = getFolder("Program");//程序根目录


var fChrome = getFolder("Chrome");//chrome目录


var fComponents = getFolder("Components");//components目录




// workaround for Mozilla 1.8a3 and newer, failing to register enigmime correctly


var delComps = [ "compreg.dat" ]; // Components registry


for (var j=0; j<delComps.length; j++)






{


var delFile = getFolder(fComponents, delComps[j]);


if (File.exists(delFile))


File.remove(delFile);


}




err = getLastError();


if (err == DOES_NOT_EXIST)






{


// error code: file does not exist


resetError();


}


else if (err != SUCCESS)






{


cancelInstall(err);


}




// addDirectory: blank, archive_dir, install_dir, install_subdir


addDirectory("", "components", fComponents, "");


addDirectory("", "chrome", fChrome, "");






err = getLastError();


if (err == ACCESS_DENIED)






{


alert("Unable to write to components directory "+fComponents+"./n You will need to restart the browser with administrator/root privileges to install this software. After installing as root (or administrator), you will need to restart the browser one more time, as a privileged user, to register the installed software./n After the second restart, you can go back to running the browser without privileges!");


cancelInstall(ACCESS_DENIED);




}


else if (err != SUCCESS)






{


cancelInstall(err);




}


else






{


// Register chrome


registerChrome(PACKAGE | DELAYED_CHROME, getFolder("Chrome","helloworld.jar"), "content/helloworld/");


err = getLastError();


if (err != SUCCESS)






{


cancelInstall(err);


}


else






{


performInstall();


}


}



2)在Componts文件夹中加入MyComponent.dll和IMyComponent.xpt

3)修改overlay.js如下:


// This is the main function


const ENIG_C = Components;


const ENIG_ENIGMAIL_CONTRACTID = "@mydomain.com/XPCOMSample/MyComponent;1"


var gEnigmailSvc = null;




function helloWorld()






{


try






{


alert("准备创建组件");


gEnigmailSvc = ENIG_C.classes[ENIG_ENIGMAIL_CONTRACTID].createInstance(ENIG_C.interfaces.IMyComponent);//创建实例


if(gEnigmailSvc!=null)






{


alert("创建组件成功");


gEnigmailSvc = gEnigmailSvc.QueryInterface(ENIG_C.interfaces.IMyComponent);


}


else






{


alert("创建组件失败");


return;


}


var res = gEnigmailSvc.Add(3, 4);


alert('Performing 3+4. Returned ' + res + '.');


alert("创建结束");


}


catch(ex)






{


alert("error");


}


}



好了,到此就完成了这个最简单的XPCOM组件的开发了,enjoy it!

Reference
[/b]

1,利用VC创建XPCOM组件
2, http://enigmail.mozdev.org/home/index.php
需要完整代码的,请发email至phinecos@163.com,也欢迎有兴趣的朋友们一起来交流Mozilla的扩展开发技术
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: