XPCOM
LINUX下的组件开发技术
COM技术作为微软推行的一种组件技术,在WINDOWS平台站有重要地位,在模块重用,跨语言通信等方面都能见到其身影。但今天给我要介绍的是LINUX下的COM实现----XPCOM,这是MOZILLA浏览器项目中所使用的基本技术,我们可以用C++制作XPCOM组件,在C++客户程序或MOZILLA浏览器中通过JAVASCRIPT脚本来调用组件,从而实现软件模块的复用。
1、         配置XPCOM的开发环境。
首先到MOZILLA的FTP下载Gecko-sdk包,这是XPCOM的开发包,MOZILLA的源码中也包括该SDK。解压该tgz包,可以看到生成大约十多个目录:
/sdk/gecko-sdk/
/sdk/gecko-sdk/xpcom/bin
/sdk/gecko-sdk/xpcom/idl
/sdk/gecko-sdk/xpcom/include
/sdk/gecko-sdk/nspr
......
这里说明一下其中的一些基本部分。
/sdk/gecko-sdk/xpcom/bin下主要包含了一些文件:
xpidl:这是idl编译器,用以根据idl产生c++头文件或组件类型库文件.
Regxpcom:这是组件注册工作,如果我们在MOZILLA浏览器中调用组件,其实不会用该工具。
Xpt-dump:类型库查看程序,用来查看.xpt文件中的组件信息。
libxpcomglue.a:这是XPCOM的基本库文件,在生成组件时将会被连接到我们的组件库中。
/sdk/gecko-sdk/xpcom/idl,该目录中包含了idl数据类型定义文件。
/sdk/gecko-sdk/xpcom/include,其中包含了制作XPCOM时所需要的基本的C++头文件。
/sdk/gecko-sdk中还包含了其它一引起目录,如/sdk/sdk/gecko-sdk/string/include,其中包含了XPCOM中常字符串类的C++头
文件,如果我们的组件中需要使用这些类,只需包含进必要的头文件及库文件即可。
2、         撰写idl文件。
这里要先用到一个uuidgen(LINUX下类似MS GUIDGEN的一个命令行程序)用以产生组件的uuid, 我们将其输出先重定向到一个文本中,呆会儿即可使用,这里我们举一个简单的例子,来演示组件的生成过程。
Idl文件如下:
//filename: nsIMyCom.idl
//begin idl --------------------------------------
#include "nsISupports.idl"
[scriptable,  uuid(5217115e-11fe-4d01-966d-9b27ffda6498)]
interface nsIMyCom:nsISupports
{
void Hello(in string in_str, [retval] out string out_str);
};
//end idl-----------------------------------------
好了,该组件很简单,只有一个接口,并且也只有一个方法,该方法有一个字符串输入参数in_str,并且有一个字符串返回值out_str。
3、编译该idl文件,并完成该组件对应的C++实现。
/sdk/gecko-sdk/xpcom/bin/xpidl -I/sdk/gecko-sdk/xpcom/bin/idl -m header nsIMyCom.idl
如果没有错误,这时在当前目录下将会生成一个nsIMyCom.h文件,该文件是idl编译器对应上面的idl文件所生成的c++头文件。
下面是编译器生成的nsIMyCom.h文件内容:
//--------------------------------------------------------
#ifndef __gen_nsIMyCom_h__
#define __gen_nsIMyCom_h__
#ifndef __gen_nsISupports_h__
#include "nsISupports.h"
#endif
/* For IDL files that don't want to include root IDL files. */
#ifndef NS_NO_VTABLE
#define NS_NO_VTABLE
#endif
/* starting interface:    nsIMyCom */
#define NS_IMYCOM_IID_STR "5217115e-22fe-4d01-966d-9b27ffda6498"
#define NS_IMYCOM_IID /
{0x5217115e, 0x22fe, 0x4d01, /
{ 0x96, 0x6d, 0x9b, 0x27, 0xff, 0xda, 0x64, 0x98 }}
class NS_NO_VTABLE nsIMyCom : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMYCOM_IID)
/* void Hello (in string in_str, [retval] out string out_str); */
NS_IMETHOD Hello(const char *in_str, char **out_str) = 0;
};
/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_NSIMYCOM /
NS_IMETHOD Hello(const char *in_str, char **out_str);
/* Use this macro to declare functions that forward the behavior of this interface to another object. */
#define NS_FORWARD_NSIMYCOM(_to) /
NS_IMETHOD Hello(const char *in_str, char **out_str) { return _to Hello(in_str, out_str); }
/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe
way. */
#define NS_FORWARD_SAFE_NSIMYCOM(_to) /
NS_IMETHOD Hello(const char *in_str, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->Hello
(in_str, out_str); }
#if 0
/* Use the code below as a template for the implementation class for this interface. */
/* Header file */
class nsMyCom : public nsIMyCom
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMYCOM
nsMyCom();
virtual ~nsMyCom();
/* additional members */
};
/* Implementation file */
NS_IMPL_ISUPPORTS1(nsMyCom, nsIMyCom)
nsMyCom::nsMyCom()
{
/* member initializers and constructor code */
}
nsMyCom::~nsMyCom()
{
/* destructor code */
}
/* void Hello (in string in_str, [retval] out string out_str); */
NS_IMETHODIMP nsMyCom::Hello(const char *in_str, char **out_str)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* End of implementation class template. */
#endif
#endif /* __gen_nsIMyCom_h__ */
//---------------------------------------------------------
从上面可以看到, xpidl生成了对应该接口的头文件,同时还包括对该头文件实现的C++类模板.下一步的工作一样很轻松,
我们将#if 0 至#endif 之间的代码分别复制到新建的nsMyCom.h 和nsMyCom.cpp文件中,
注意其中有新增的代码,下面是生成的两个文件.
//filename: nsMyCom.h
#include "nsImyCom.h"
#define NS_MYCOM_CID /
{0x5217115e, 0x22fe, 0x4d01, { 0x96, 0x6d, 0x9b, 0x27, 0xff, 0xda, 0x64, 0x98 }}     
//类似WINDOWS 中CLSID
#define NS_MYCOM_CONTRACTID "@westsoft.org/mycom;1"   //类似WINDOWS中的progid;
class nsMyCom : public nsIMyCom
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMYCOM
nsMyCom();
virtual ~nsMyCom();
/* additional members */
};
//filename: nsMyCom.cpp
#include "nsMyCom.h"
#include "nsMemory.h"
#include <cstdio>
#include <cstdlib>
#include <string>
NS_IMPL_ISUPPORTS1_CI(nsMyCom, nsIMyCom)      //此处的宏已修改.
nsMyCom::nsMyCom()
{
}
nsMyCom::~nsMyCom()
{
}
/* void Hello (in string in_str, [retval] out string out_str); */
NS_IMETHODIMP nsMyCom::Hello(const char *in_str, char **out_str)
{
printf("/n-----------------/n");
printf("%s/n", in_str);
std::string str_tmp = "your input is: ";
str_tmp += in_str;
*out_str = (char*)malloc(str_tmp.length() + 1);
*out_str = (char*)str_tmp.c_str();
return NS_OK;
}
4、完成组件的工厂方法及注册模块。
组件本身的实现就上面两个类即可以了. 但是我们仅把上面的类生成动态库是不能作为组件工作的,我们还需要做一件事情.实现组件的注册及创建相关的功能.这几乎是一个固定的模式.
下面是该部分的代码,跟MS中的实现类似,用了许多的宏:
#include "nsIGenericFactory.h"
#include "nsMyCom.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMyCom)
static NS_METHOD nsMyComRegistrationProc(nsIComponentManager *aCompMgr,
nsIFile *aPath, const char *registryLocation, const char *componentType, const nsModuleComponentInfo *info)
{
return NS_OK;
}
static NS_METHOD nsMyComUnregistrationProc(nsIComponentManager *aCompMgr,
nsIFile *aPath,   const char *registryLocation,   const nsModuleComponentInfo *info)
{
return NS_OK;
}
NS_DECL_CLASSINFO(nsMyCom)
static const nsModuleComponentInfo components[] ={
{ "nsMyCom Component", NS_MYCOM_CID, NS_MYCOM_CONTRACTID,nsMyComConstructor,
nsMyComRegistrationProc /* NULL if you dont need one */,
nsMyComUnregistrationProc /* NULL if you dont need one */,
NULL /* no factory destructor */,
NS_CI_INTERFACE_GETTER_NAME(nsMyCom),
NULL /* no language helper */,
&NS_CLASSINFO_NAME(nsMyCom)
}
};
NS_IMPL_NSGETMODULE(nsMyComModule, components)
5、制作Makefile,生成,安装组件
好了,我们可以编写Makefile文件,来编译我们刚才编写的组件了.
#filename:Makefile
#begine-------------------------------------
CPP = g++
CPPFLAGS += -fno-rtti -fno-exceptions -shared
GECKO_SDK_PATH = /sdk/gecko-sdk
XPIDL = $(GECKO_SDK_PATH)/xpcom/bin/xpidl
CPPHEADER = -m header
TYPELIB = -m typelib
REGDIR = /usr/local/lib/mozilla-1.6
OUTDIR = $(REGDIR)/components
GECKO_CONFIG_INCLUDE = -include mozilla-config.h
GECKO_DEFINES  = -DXPCOM_GLUE
GECKO_INCLUDES = -I$(GECKO_SDK_PATH) /
-I$(GECKO_SDK_PATH)/xpcom/include/
-I$(GECKO_SDK_PATH)/nspr/include
GECKO_LDFLAGS =  -L$(GECKO_SDK_PATH)/xpcom/bin -lxpcomglue /
-L$(GECKO_SDK_PATH)/nspr/bin -lnspr4
GECKO_IDL = -I$(GECKO_SDK_PATH)/xpcom/idl
build: idl nsMyCom.o nsMyComModule.o
$(CPP) $(CPPFLAGS) -o libxpmycom.so $(GECKO_DEFINES) /
$(GECKO_LDFLAGS) nsMyCom.o nsMyComModule.o
chmod +x libxpmycom.so
idl: nsIMyCom.idl
$(XPIDL) $(GECKO_IDL) $(CPPHEADER) nsIMyCom.idl
$(XPIDL) $(GECKO_IDL) $(TYPELIB) nsIMyCom.idl
nsMyCom.o: nsMyCom.cpp
$(CPP) $(GECKO_CONFIG_INCLUDE) $(GECKO_DEFINES) /
$(GECKO_INCLUDES) -c nsMyCom.cpp -o nsMyCom.o
nsMyComModule.o: nsMyComModule.cpp
$(CPP) $(GECKO_CONFIG_INCLUDE) $(GECKO_DEFINES) /
$(GECKO_INCLUDES) -c nsMyComModule.cpp -o nsMyComModule.o
install:
cp nsIMyCom.xpt $(OUTDIR)/
cp libxpmycom.so $(OUTDIR)/
clean:
rm *.o
rm *.so
rm *.*~
rm *~
#end-------------
如果一切无误,我们make之后,g++就会在当前目录下生成libxpmycom.so库文件。然后再将该组件安装到mozilla的组件目录中:
make install
该组件库及对应的类型库nsIMyCom.xpt将会被拷到/usr/local/lib/mozilla-1.6/components(要确认你的组件目录,如mozilla1.4目录一般为usr/local/lib/mozilla-1.4/components)目录中。
这时我们可以从控制台启动mozilla浏览器,在浏览器输出的一系列信息中,将会有该组件被注册成功的信息。
6、在html/javascript中测试该组件。
该html如下:
//------------------------------------
<html>
<head>
<title>
测试XPCOM组件
</title>
</head>
<body>
<script>
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var mycom = Components.classes["@westsoft.org/mycom;1"].createInstance();
mycom = mycom.QueryInterface(Components.interfaces.nsIMyCom);
function testxpcom(f)
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var ret_string;
ret_string = mycom.Hello(document.form_test.input_string.value);
alert(ret_string);
}
</script>
<form name="form_test">
输入信息:
<textarea name = "input_string" cols = "70" rows = "5"></textarea>
<input type="button" value="testxpcom" onClick = "testxpcom(this.form);">
</form>
</body>
</html>
//--------------------------------------------------
我们在mozilla中打开该html,在输入框中输入一些文字,在点击testxpcom后,怎么样,看到从组件返回的信息了吗?
另外,上面的输入信息如果是中文,则返回中会产生乱码,xpcom idl中有nsAString, wstring等支持unicode的字符串类型,由于在参数的传递中会涉及一些转换,因而未提及。
以上只是展示了 XPCOM组件的基本技术,还有许多内容未提及,如果要将该技术应用于项目中,更多的资料请查阅mozilla的网上资源。

firefox的XPCOM的COM编程相关推荐

  1. 如何编写firefox插件

    转帖至:http://www.ibm.com/developerworks/cn/web/wa-lo-firefox-ext/index.html 本文中所要构建的是一个能够批量下载某个 HTML 页 ...

  2. Mozilla的架构(收集)

    Mozilla的架构 原文发表于<程序员>2007第5期,BLOG首发. Firefox的横空出世在很多人的意料之外,其体积小巧功能强大,在安全性.扩展性和可移植性上都有惊人的表现.这样优 ...

  3. C++ 的未来——第 2 部分

    C++ 正处于一个挑战时间点.在第一部分,我们讨论了 Sean Parent 在 Cpp North 2022 大会上提出的"C++ 的悲剧".在第二部分,我们将讨论 C++ 的替 ...

  4. python写签到软件_第一个实用python程序——自动填写工作日志、签到

    刚刚把文章重看了一遍,自己给的评价就是:闲的没事干了? 1. 前言 一直苦于每天要分上下午两次写工作日志(不太能理解单位某些部门的脑洞--一天一次不行么?噢--噢噢,好吧,你们抄的模板就是分上下午的, ...

  5. 大数据学习笔记之Linux基础(一):Linux初窥

    文章目录 一.Linux入门概述 1.1 概述 1.2 下载地址 1.3 Linux特点 1.4 Linux和Windows区别 二.VM安装相关 2.1 安装VMWare虚拟机 2.2 安装Cent ...

  6. 话说13款浏览器哪个好?

    这片文章是我在想换个好用的浏览器时看到的,不知道浏览器哪个好用呀,就BAIDU了--(或说Google撤退了--我才刚刚习惯用的说)发现了这篇文感觉还挺好的,至少对我这种普通的小灰用户们(我们不是小白 ...

  7. [远控免杀]msf生成木马的信息储备

    1.msfvenom的命令使用 Options:-p, --payload <payload> 指定需要使用的payload(攻击荷载).如果需要使用自定义的payload,请使用'-'或 ...

  8. 火狐 load xpcom_为Firefox浏览器创建并实现XPCOM组件

    火狐 load xpcom 跨平台组件对象模型(XPCOM)是Mozilla的跨平台组件模型,类似于CORBA和Microsoft®COM. 它具有多种语言绑定和IDL描述,因此XPCOM组件可以在J ...

  9. [转载] firefox与ie的javascript兼容性编程汇编

    1. document.formName.item("itemName") 问题 说明:IE下,可以使用document.formName.item("itemName& ...

最新文章

  1. java非递归方式实现快速排序
  2. [译]ChipMunk 教程1 - 设置
  3. Redis 分布式缓存 Java 框架
  4. 超图理论的一点理解(一)
  5. BZOJ 4241 分块
  6. 没人说得清深度学习的原理 只是把它当作一个黑箱来使
  7. android 之手机拨号器,以及短信发送器的简单实现
  8. XenApp / XenDesktop 7.6 初体验一   安装, 配置站点和序列号服务器
  9. live2d手机制作软件_live2d制作器手机版
  10. putty怎么进入文件夹_如何安装及使用PuTTY
  11. PDF在文字方面的一个缺陷
  12. python - 文件打包发布流程
  13. 基于低代码为企事业单位打造督办事务管理一体化协同管控平台
  14. 沁透著一片悠然禪意 《掬水》
  15. 创业前期怎么做个简单易行的计划?
  16. [NFC]NDEF和RTD协议介绍
  17. Liunx——参考数据与延伸阅读
  18. 珍惜身边所有,因为来日不方长。
  19. git commit 提交报错 husky > pre-commit 问题
  20. 运维人必备:日志分析工具日志易之银行业解决方案

热门文章

  1. 【C语言】二维数组定义以及引用
  2. PA1.3 代码+笔记
  3. 学了python能找人吗_只学python能找工作吗
  4. Linux shell脚本入门到实战详解(一)
  5. 一项调查:从浅到深的机器学习方法的血压估计使用生物传感器【翻译】
  6. H5 iOS 自动调起软键盘
  7. 写在“华为伙伴暨开发者大会”前夕:给昇腾AI划三个重点
  8. 流量威胁检测工具开发之路(7)
  9. LPC1768学习笔记
  10. linux watch 查看文件,linux watch肿么退出