65.9K
CodeProject 正在变化。 阅读更多。
Home

将 Microsoft COM 转换为 XPCOM

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (15投票s)

2010年7月26日

CPOL

4分钟阅读

viewsIcon

43443

downloadIcon

491

从 Microsoft COM 到 XPCOM 的逐步创建

文章目的

我为刚开始接触 XPCOM 但对 Microsoft COM 有深入了解的程序员编写了本教程。本文简要介绍了如何编写自己的 XPCOM 对象,并使用 VC8.0 将 MsCOM 转换为 XPCOM。本文不涵盖 XPCOM 的基础知识或概念。

项目设置或开发环境对我来说曾是一个大问题。此外,XPCOM 的注册也是一个棘手的问题,因为必须从配置文件目录中删除 xpti.datcompreg.dat

我还为 XPCOM 初学者写过一篇名为 A Simple XPCOM Tutorial 的文章。

引言

XPCOM 是一个跨平台组件对象模型,类似于 Microsoft COM。它具有多种语言绑定,允许 XPCOM 组件除了 C++ 之外,还可以用 JavaScript、Java 和 Python 进行使用和实现。XPCOM 中的接口定义在一种称为 XPIDL 的 IDL 方言中。

对我而言,理解 XPCOM 无疑是一次漫长的探索。我认为,任何希望理解 XPCOM 基本原理的程序员,都必须至少用纯 C++ 编写一个简单的 XPCOM 对象。在本文中,我将介绍将 MsCOM 转换为简单 XPCOM 对象并使其能够被 VC++/JavaScript 客户端使用的指导方针。

作为一项练习,我们将尝试设计一个 XPCOM 组件,它将实现一个假想的超快速加法算法。该组件必须接受两个 long 类型的数据参数,并向用户返回另一个 long 类型参数,该参数将是我们加法算法的结果。

如何从 Microsoft COM 创建 XPCOM

第一步:开发环境设置

  • 请使用适合您的 XULRunner 版本的 xulrunner SDK,我使用的是 xulrunner-1.9.2。
  • 请使用 Microsoft 编译器,我使用的是 Visual C++ 2005。

这是我的文件夹结构:

XPCOM
    - xulrunner-sdk
        bin
        lib
        idl
        include
               
    - sample_xpcom  (xpcom creation)
        Debug
        Release

第二步:创建 VC++ 项目

  • 在 Visual Studio 中启动一个空的 Win32 项目,并选择“动态链接库 (DLL)”选项。
  • 进行以下调整:
    • 将 “..\xulrunner-sdk\include” 添加到附加包含目录。
    • 将 “..\xulrunner-sdk\lib” 添加到附加库目录。
    • 将 “nspr4.lib xpcom.lib xpcomglue_s.lib” 添加到附加依赖项。
    • 将 “XP_WIN;XP_WIN32” 添加到预处理器定义。
    • 关闭预编译头(为了简单起见)。

第三步:创建 IDL 文件

  • XPCOM 使用 “include” 来导入 IDL 文件。
  • 定义接口属性。
  • 所有 XPCOM 接口都继承自 nsISupports 接口。因此,请让您的接口继承自 “nsISupports”。
  • 定义库不是必需的。
  • 为 XPCOM IDL 文件使用自定义生成步骤(从 MIDL 构建中排除)。

第四步:编译 IDL 文件

  • MsCOM 使用 MIDL.exe 编译。但 XPCOM 使用 XPIDL.exe 编译。对于 MsCOM:

    {path_to_ Vs_Tools }\bin\Midl.exe /I /Oicf {your_idl_file}
  • 对于 XPCOM,需要使用 xpidl 编译两次,以创建头文件和类型库。
    {path_to_ xulrunner-sdk }\bin\xpidl.exe 
    	-m header -I..\ xulrunner-sdk \idl {your_idl_file} 
    {path_to_ xulrunner-sdk }\bin\xpidl.exe 
    	-m typelib -I..\ xulrunner-sdk \idl {your_idl_file}

    将创建一个类型库 (*.XPT) 和一个 C++ 头文件 (*.H)。

第五步:创建实现文件(头文件和 CPP)

头文件

  • 包含生成的接口头文件。
  • 定义组件契约 ID。组件契约 ID 的推荐格式如下一行字符串:
    “@<internetdomain/>/module[/submodule[...]];<version/>
    	[?<name/>=<value/>[&<name/>=<value/>[...]]]”
  • 定义类名,与 MSCOM 属性中的帮助字符串相同 - 定义组件 ID,即接口的 UUID。
  • 定义类,只需继承该接口。
  • 声明 COM 入口映射。

    对于 MsCOM:

    BEGIN_COM_MAP(YourClassName)
    	COM_INTERFACE_ENTRY(InterfaceName)
    	COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()

    但对于 XPCOM:

    NS_DECL_ISUPPORTS
    NS_DECL_ISAMPLE
  • 声明方法和属性。

CPP 文件

  • 包含头文件。
  • 实现 COM 入口映射。
  • 定义方法。

第六步:创建模块文件

  • 定义包含 XPCOM 组件的模块文件。
  • RGS 文件不是必需的,因为 XPCOM 不使用 Windows 注册表。
  • DEF 文件不是必需的。

第七步:注册 DLL

  • 将您的 XPT 和 DLL 文件复制到 Firefox 的 components 目录。
  • MsCOM 使用 REGSVR32.exe 注册。
    “regsvr32 {yourMsCOM dll} “
  • 但 XPCOM 使用 REGXPCOM.exe 注册。
  • 从您的配置文件目录中删除 xpti.datcompreg.dat(如果存在 “components.list” 文件,请在末尾添加 “yourXPCOM DLL”)。Firefox 将在下次启动时重新生成它们,或者我们可以像这样使用 regxpcom.exe
    “regxpcom -x { FireFoxDir }\bin {FireFoxDir}\components\{yourXPCOM dll}"

Using the Code

现在启动示例。

这是 MsCOM 的 IDL 文件。

import "oaidl.idl";
import "ocidl.idl";

[
    object,
    uuid(668C357B-5FB9-4743-8FE8-591B40ECE9A2),
    dual,
    nonextensible,
    helpstring("ISampleAdd Interface"),
    pointer_default(unique)
]
interface ISampleAdd : IDispatch
{
    [id(1), helpstring("method Add")] HRESULT Add([in] LONG FisrtNumber, [in]
                  LONG SecondNumber, [out,retval] LONG* ResultValue);
};
    
/*
Definition of library which is not required for xpcom
*/

将此 IDL 修改如下:

#include "nsISupports.idl"

[scriptable, uuid(658ABC9E-29CC-43E9-8A97-9D3C0B67AE8B)]
// here I used scpiptable to support scripting languages to access this component
interface ISample : nsISupports
{
    long	Add(in long a, in long b);  
};

编译 IDL。

  • 对于 MsCOM,我们可以这样编译:
    MidL /I /Oicf Sample_mscom.idl

    使用 midl 编译会创建 5 个文件:

    Sample_mscom.h 包含 C++ 风格的接口声明。
    dlldata.c 包含代理 DLL 的代码。在跨进程/跨计算机调用对象时很有用。
    Sample_mscom.tlb 二进制文件,具有明确定义的格式,完整描述了我们的 IAdd 接口及其所有方法。此文件将分发给我们的 COM 组件的所有客户端。
    Sample_mscom_p.c 包含代理 DLL 的封送代码。在跨进程/跨计算机调用对象时很有用。
    Sample_mscom_i.c 包含接口 IID。
  • 但对于 XPCOM,我们需要使用 xpidl 编译。每次编译会创建一个文件。

    在这里,我们需要这样编译:

    {path_to_ xulrunner-sdk }\bin\xpidl.exe 
    	-m header -I ..\ xulrunner-sdk \idl ISample.idl 
    
    {path_to_ xulrunner-sdk }\bin\xpidl.exe 
    	-m typelib -I ..\ xulrunner-sdk \idl ISample.idl 
  • 在这里,我们将得到两个文件:

    ISample.h 包含 C++ 风格的接口声明。
    ISample.xpt 二进制文件,具有明确定义的格式,完整描述了我们的 IAdd 接口及其所有方法。此文件将分发给我们的 XPCOM 组件的所有客户端。

头文件

#include "ISample.h"

#define SAMPLE_COMPONENT_CONTRACTID "@cn.ibm.com/XPCOM/sample;1"
#define SAMPLE_COMPONENT_CLASSNAME "Sample XPCOM Interface Layer"
#define SAMPLE_COMPONENT_CID  { 0x658abc9e, 0x29cc, 0x43e9,
	{ 0x8a, 0x97, 0x9d, 0x3c, 0x0b, 0x67, 0xae, 0x8b } }

class CSample : public ISample
{
public:
    /* Use this macro when declaring classes that implement this interface. */
    NS_DECL_ISUPPORTS 
    NS_DECL_ISAMPLE
    	
    CSample();
    virtual ~CSample();

    //additional member functions
    int Add();
};

CPP 文件

#include "Sample.h"

//This macro automatically adds the nsISupports entry
NS_IMPL_ISUPPORTS1(CSample, ISample)

CSample::CSample()
{
    /* member initializers and constructor code */
}

CSample::~CSample()
{
    /* destructor code */
}

/* long Add (in long a, in long b); */
NS_IMETHODIMP CSample::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)
{
    *_retval = a + b;
    	
    return NS_OK;
}

模块文件

#include "nsIGenericFactory.h"
#include "Sample.h"

// This results in a function called CSampleConstructor that 
// can be used in the nsModuleComponentInfo structure.
NS_GENERIC_FACTORY_CONSTRUCTOR(CSample)

static nsModuleComponentInfo components[] =
{
    {
	    SAMPLE_COMPONENT_CLASSNAME,
	    SAMPLE_COMPONENT_CID,
	    SAMPLE_COMPONENT_CONTRACTID,
	    CSampleConstructor,
    }
};

// Implements the nsIModule interface with the module name of name and 
// the component list in components.
NS_IMPL_NSGETMODULE("sample_module", components)

注意:学习此内容的简便方法是直接使用项目。构建这些项目,您还可以从我的 “A Simple XPCOM Tutorial” 中获得帮助。如果您有任何建议、请求或问题,请告知我。

历史

  • 2010 年 7 月 26 日 首次发布
© . All rights reserved.