XPCOMの作成 編集

古い情報がたくさん流れています。 新しい情報は何処にあるやら…

SDKの入手 編集

JSのXPCOM 編集

計算をするXPCOM、myCalcを作る。

  • myCalcはaddというメソッドだけをもつオブジェクト。
  • myCalc.addは数値を2つ引数として受け取って、それらの数値を足した結果を返す。
  • 例: myCalc.add(3, 4) // -> 7 拡張機能の作成などの部分はスキップして、XPCOMを作る所だけ。
  1. xxIxxx.idl(myICalc.idl)を作る
  2. xpidlでxxIxxx.xpt(myICalc.xpt)を作成
  3. xxxxx.js(myCalc.js)を作成
xxIxxx.idl(myICalc.idl)を作る 編集
#include "nsISupports.idl"
[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]  # ←GUIDを生成して使用
interface myICalc : nsISupports   # ←(プレフィクス)I(インターフェース名)
{
  long add(in long a, in long b);
};
xpidlでxxIxxx.xpt(myICalc.xpt)を作成 編集
xpidl -m typelib -I c:\xxx_gecko_sdk myICalc.idl
  • Iオプションの引数は、Gecko SDK内のidlディレクトリへのパス。これを指定しないとnsISupports.idlのインクルードに失敗する。
xxxxx.js(myCalc.js)を作成 編集
function myCalc(){} // ←(プレフィクス)(インターフェース名)

myCalc.prototype={
  get contractID(){
    return "@mydomain.example.jp/xpcom-sample/Calc;1";  // ← @(ドメイン)/(コンポーネント名)/(インターフェース名);(バージョン)
  },
  get classDescription(){
    return "This is a Sample";
  },
  get classID(){
    return Components.ID("{yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy}"); // ←GUIDを生成して使用 (インターフェースとは別のもの)
  },
  add:function(a,b){
  return a+b;
  },
  QueryInterface:function(aIID){
    if(!aIID.equals(Components.interfaces.myICalc) && !aIID.equals(Components.interfaces.nsISupports))
      throw Components.results.NS_ERROR_NO_INTERFACE;
    return this;
  }
}



var gModule = {
  registerSelf: function (aComponentManager, aFileSpec, aLocation, aType) 
  {
    aComponentManager = aComponentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
    for (var key in this._objects) {
      var obj = this._objects[key];
      aComponentManager.registerFactoryLocation(obj.CID, obj.className, obj.contractID, aFileSpec, aLocation, aType);
    }
  },
  getClassObject: function (aComponentManager, aCID, aIID) 
  {
    if (!aIID.equals(Components.interfaces.nsIFactory))
      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

    for (var key in this._objects) {
      if (aCID.equals(this._objects[key].CID))
        return this._objects[key].factory;
    }
    
    throw Components.results.NS_ERROR_NO_INTERFACE;
  },
  
  _objects: {
    manager: { CID        : myCalc.prototype.classID,
               contractID : myCalc.prototype.contractID,
               className  : myCalc.prototype.classDescription,
               factory    : {
                              createInstance: function (aOuter, aIID) 
                              {
                                if (aOuter != null)
                                  throw Components.results.NS_ERROR_NO_AGGREGATION;
                                return (new myCalc()).QueryInterface(aIID);
                              }
                            }
             }
   },
  
  canUnload: function (aComponentManager) 
  {
    return true;
  }
};

function NSGetModule(compMgr, fileSpec) 
{
  return gModule;
}
XPCOMの登録と使用 編集

作成したxxIxxxx.xpt(myICalc.xpt)とxxxxxx.js(myCalc.js)を拡張機能の components ディレクトリに置くだけ。拡張機能をインストールしてFirefoxを再起動した後、ユーザープロファイル内のcompreg.datの中に「myCalc」という文字列があれば、正常に登録されている。以下の要領で使用可能。

var calc = Components
             .classes["@mydomain.example.jp/xpcom-sample/Calc;1"]
             .getService(Components.interfaces.myICalc);

C++のXPCOM 編集

  1. xxIxxx.idlを作る
  2. xpidlでxxIxxx.xptとxxIxxx.hを作成
  3. xxIxxx.hからxxxxx.hとxxxxx.cppとxxxxxModule.cppを作成
  4. Makefile.inを作成、Firefoxと一緒にビルド
xxIxxx.idlを作る 編集
#include "nsISupports.idl"
[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]
interface xxIxxx : nsISupports
{
  long add(in long a, in long b);
};
xpidlでxxIxxx.xptとxxIxxx.hを作成 編集
xpidl -m typelib -I c:\xxx_gecko_sdk xxIxxx.idl
xpidl -m header -I c:\xxx_gecko_sdk xxIxxx.idl
xxIxxx.hからxxxxx.hとxxxxx.cppとxxxxxModule.cppを作成 編集
*xxxxx.h 編集

xxIxxx.hにある/* Header file */から/* Implementation file */の手前までをxxxxx.hにコピペ

~xxxxx()をvirtual ~xxxxx()に置換

#ifndef _XX_XXX_H_
#define _XX_XXX_H_

#include "xxIxxx.h"

#define XX_XXX_CONTRACTID "@xxx.xxx.jp/xx_ext/xxx;1"
#define XX_XXX_CLASSNAME "This is Sample"
#define XX_XXX_CID {0x00000000, 0x0000, 0x0000, \
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}

を先頭に追加(XX_XXX_CIDはxxIxxx.hのXXXXX_IIDをコピペする)

#endif //_XX_XXX_H_

を後方に追加

*xxxxx.cpp 編集

xxIxxx.hにある/* Implementation file */からの/* End of implementation class template. */までをxxxxx.cppにコピペ

#include "xxxxx.h"

を先頭に追加

*xxxxxModule.cpp 編集
#include "nsIGenericFactory.h"
#include "xxxxx.h"

NS_GENERIC_FACTORY_CONSTRUCTOR(xxxxx)

static nsModuleComponentInfo components[] =
{
    {
       XX_XXX_CLASSNAME, 
       XX_XXX_CID,
       XX_XXX_CONTRACTID,
       xxxxxConstructor,
    },
};

NS_IMPL_NSGETMODULE(xxxxxModule, components)
Makefile.inを作成、Firefoxと一緒にビルド 編集

まだビルドに成功してないので保留

  • 適当にXPCOMについてまとめました。誰か足りないところの穴埋め頼みます。 -- by 謎 at 2005-08-08 18:52:49 (月)

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

C++のXPCOM on Linux 編集

↑と同じく、元ネタはここ。

計算をするXPCOM、myCalcを作る。拡張機能としてインストールし、 ためしに使ってみるところまで。

  • myCalcはaddというメソッドだけをもつオブジェクト。
  • myCalc.addは数値を2つ引数として受け取って、それらの数値を足した結果を返す。
  • 例: myCalc.add(3, 4) // -> 7

Debian GNU/Linux上での話。

ソースはここ

以下、作り方。

作業用ディレクトリを作っておくこと。

% mkdir -p xpcom-sample/{content/xpcom-sample,components}
% cd xpcom-sample
拡張機能の作成 編集

いきなりXPCOMの作り方にいくと思ったら大間違い。まずは、XPCOM をインストールする拡張機能を作る。

install.rdf:

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
  <Description about="urn:mozilla:install-manifest">
    <em:id>xpcom-sample@cozmixng.org</em:id>
    <em:name>XPCOM sample</em:name>
    <em:version>0.1</em:version>
    <em:description>XPCOM sample</em:description>
    <em:creator>Kouhei Sutou</em:creator>

    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
        <em:minVersion>2.0</em:minVersion>
        <em:maxVersion>2.0.0.*</em:maxVersion>
      </Description>
    </em:targetApplication>
  </Description>
</RDF>

chrome.manifest:

content	xpcom_sample	content/
overlay	chrome://browser/content/browser.xul	chrome://xpcom_sample/content/overlay.xul

インストーラ作成スクリプトも作る。

dist.sh:

#!/bin/sh

cd `dirname $0`

#basename=`basename $PWD`
basename=xpcom-sample
version=`grep '<em:version>' install.rdf | sed -e 's,</\?em:version>,,g'`
version=`echo $version | sed -e 's/[[:space:]]//g'`

xpi=$basename-$version.xpi

if [ -f components/Makefile ]; then
    (cd components && make) || exit 1
    component_shared="components/myCalc.so"

    component_xpt="components/myICalc.xpt"
    components="$component_xpt $component_shared"
fi
xpi_contents="content $components chrome.manifest install.rdf"

rm -f $xpi
zip -q -r -9 $xpi $xpi_contents -x \*/.svn/\* || exit 1

dist.shを実行し.xpiを作成する。

% ./dist.sh

カレントディレクトリにxpcom-sample-0.1.xpiが作成されているは ずなので、それをインストール。

% iceweasel xpcom-sample-0.1.xpi

「ツール」→「アドオン」で「XPCOM sample」がインストールされ ていることを確認する。

それでは、準備ができたのでXPCOMを作成していく。

IDLの作成 編集

まずは、IDL、components/myICalc.idlを作成する。XPCOMは components以下に作成すること。そうすると、Firefoxが自動で XPCOMを検出して読み込めるようにしてくれる。そうしないと、リン ク先にあるように手動で登録しなくてはいけなくなって、はまる。

IDL中のuuidはuuidgenで生成する。

% uuidgen
c95498ae-16f5-4b46-8713-2cf79e30d4ef

compornts/myICalc.idl:

#include "nsISupports.idl"
[scriptable, uuid(c95498ae-16f5-4b46-8713-2cf79e30d4ef)]
interface myICalc : nsISupports
{
  long add(in long a, in long b);
};
.xptと.hの生成 編集

次にIDLから.xptと.hを生成する。.xptはたぶん、このXPCOMはこう いう名前でこういうプロパティを持っていますよ~、とかいう情報 なんだと思う。.hはそのプロトタイプ宣言とか。(ここは適当に書 いている)

.xpiと.hはxpidlを使って作る。これは.idlを更新するたびに行う必 要がある。たぶん、これからたくさん起こることなのでMakefileを 作っておく。

ここではXULRunnerを使っている(Debianではxulrunnerパッケー ジ)。他の環境でやる場合はGECKO_PATHとかGECKO_XXX_PATHを変更 する必要があるだろう。

components/Makefile:

GECKO_PATH = /usr/lib/xulrunner
GECKO_SDK_PATH = $(GECKO_PATH)/sdk

GECKO_IDL_PATH = $(GECKO_SDK_PATH)/idl

XPIDL = $(GECKO_PATH)/xpidl

IDL = myICalc.idl
XPT = myICalc.xpt
IHEADER = myICalc.h

all: $(XPT) $(IHEADER)

$(XPT): $(IDL)
	$(XPIDL) -m typelib -I$(GECKO_IDL_PATH) $(IDL)

$(IHEADER): $(IDL)
	$(XPIDL) -m header -I$(GECKO_IDL_PATH) $(IDL)

clean:
	rm -f $(XPT) $(IHEADER)

実は最初に作ったdist.shにはcomponentsでmakeするコードも入って いる。ということで、dist.shを実行して.xpiを生成し、再びインス トールする。

% ./dist.sh
/usr/lib/xulrunner/xpidl -m typelib -I/usr/lib/xulrunner/sdk/idl myICalc.idl
/usr/lib/xulrunner/xpidl -m header -I/usr/lib/xulrunner/sdk/idl myICalc.idl
% iceweasel xpcom-sample-0.1.xpi

.xptが認識されているかどうかは以下のようにして確認できる。

% grep xpcom-sample ~/.mozilla/firefox/*/xpti.dat

以下のような行が出たら認識されている。

4,.../extentions/xpcom-sample@cozmixng.org/components
XPCOMの実装 編集

それでは、足し算をするメソッドaddを持つmyCalcオブジェクトを実 装する。今まではファイル名に(たぶん)インターフェイス (Interface)を表すIをつけていたけど、これからはつけない。

まずは、myCalc.hを作成する。ここでもUUIDが必要になるので事前 に生成しておく。

% uuidgen
8931dfd3-edf3-4b7d-bd44-1da72064f0dc

また、以下のようなフォーマットに変換する必要がある。

8931dfd3-edf3-4b7d-bd44-1da72064f0dc
↓
8931dfd3 edf3 4b7d  bd 44 1d a7 20 64 f0 dc
↓
0x8931dfd3 0xedf3 0x4b7d  0xbd 0x44 0x1d 0xa7 0x20 0x64 0xf0 0xdc
↓
{0x8931dfd3, 0xedf3, 0x4b7d, {0xbd, 0x44, 0x1d, 0xa7, 0x20, 0x64, 0xf0, 0xdc}}

これをRubyで書くとこう。

split-uuid.rb:

#!/usr/bin/env ruby

ARGV.each do |uuid|
  uuid_components = uuid.split(/-/)
  first_components = uuid_components.slice!(0, 3)
  second_components = []
  uuid_components.each do |uuid_component|
    second_components.concat(uuid_component.scan(/../))
  end
  first_components = first_components.collect do |component|
    "0x#{component}"
  end.join(", ")
  second_components = second_components.collect do |component|
    "0x#{component}"
  end.join(", ")
  puts "{#{first_components}, {#{second_components}}}"
end

あるいはこう。

split-uuid2.rb:

#!/usr/bin/env ruby

ARGV.each do |uuid|
  uuid_components = uuid.split(/-/)
  first_components = uuid_components.slice!(0, 3)
  second_components = uuid_components.inject([]) do |result, component|
    result + component.scan(/../)
  end
  first, second = [first_components, second_components].collect do |components|
    components.collect do |component|
      "0x#{component}"
    end.join(", ")
  end
  puts "{#{first}, {#{second}}}"
end

手動でもいいのでとにかく以下のふたつの形式のUUIDを生成する。

8931dfd3-edf3-4b7d-bd44-1da72064f0dc
{0x8931dfd3, 0xedf3, 0x4b7d, {0xbd, 0x44, 0x1d, 0xa7, 0x20, 0x64, 0xf0, 0xdc}}

ヘッダファイルの雛型はcomponents/myICalc.hにあるので、それを コピーする。

components/myCalc.h:

#ifndef __MYCALC_H__
#define __MYCALC_H__

#include "myICalc.h"

#define MY_CALC_CONTRACT_ID "@cozmixng.org/xpcom-sample/Calc;1"
#define MY_CALC_CLASS_NAME "Calculator"
#define MY_CALC_CID_STR "8931dfd3-edf3-4b7d-bd44-1da72064f0dc"
#define MY_CALC_CID                                     \
  {0x8931dfd3, 0xedf3, 0x4b7d,                          \
     {0xbd, 0x44, 0x1d, 0xa7, 0x20, 0x64, 0xf0, 0xdc}}

class myCalc : public myICalc
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_MYICALC

  myCalc();

private:
  ~myCalc();

protected:
  /* additional members */
};

#endif

C++の雛型もcomponents/myICalc.hにあるので、それをコピーして、 addを実装する。

components/myCalc.cpp:

#include "mozilla-config.h"
#include "myCalc.h"

NS_IMPL_ISUPPORTS1(myCalc, myICalc)

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

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

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

components/Makefileを書き換えて、実装をコンパイルできるように する。

components/Makefile:

CXX = c++
CXXFLAGS = -g -Wall -fno-rtti -fno-exceptions -shared

GECKO_PATH = /usr/lib/xulrunner
GECKO_SDK_PATH = $(GECKO_PATH)/sdk

GECKO_IDL_PATH = $(GECKO_SDK_PATH)/idl
GECKO_INCLUDE_PATH = $(GECKO_SDK_PATH)/include
GECKO_LIB_PATH = $(GECKO_SDK_PATH)/lib

XPIDL = $(GECKO_PATH)/xpidl

GECKO_INCLUDES = -I$(GECKO_INCLUDE_PATH)
GECKO_CFLAGS  = -DXPCOM_GLUE $(GECKO_INCLUDES)

GECKO_LDFLAGS = -L$(GECKO_LIB_PATH)
GECKO_LIBS =	-lxpcomglue			\
		-lnspr4				\
		-lplds4

OBJS = myCalc.o

IDL = myICalc.idl
XPT = myICalc.xpt
IHEADER = myICalc.h
SHARED = myCalc.so

all: $(XPT) $(IHEADER) $(SHARED)

$(XPT): $(IDL)
	$(XPIDL) -m typelib -I$(GECKO_IDL_PATH) $(IDL)

$(IHEADER): $(IDL)
	$(XPIDL) -m header -I$(GECKO_IDL_PATH) $(IDL)

$(SHARED): $(IHEADER) $(OBJS)
	$(CXX) $(CXXFLAGS) $(GECKO_LDFLAGS) -o $(SHARED) $(OBJS) $(GECKO_LIBS)

clean:
	rm -f $(XPT) $(IHEADER) $(OBJS) $(SHARED)

.cpp.o:
	$(CXX) $(CXXFLAGS) $(GECKO_CFLAGS) -c $<

dist.shを実行してコンパイルするとMozillaのヘッダファイルで warningがでるのが嫌な感じ。

% ./dist.sh
c++ -g -Wall -fno-rtti -fno-exceptions -shared -DXPCOM_GLUE -I/usr/lib/xulrunner/sdk/include -c myCalc.cpp
/usr/lib/xulrunner/sdk/include/nsISupportsBase.h:80: warning: ‘class nsISupports’ has virtual functions but non-virtual destructor
/usr/lib/xulrunner/sdk/include/nsIProgrammingLanguage.h:32: warning: ‘class nsIProgrammingLanguage’ has virtual functions but non-virtual destructor
/usr/lib/xulrunner/sdk/include/nsIClassInfo.h:33: warning: ‘class nsIClassInfo’ has virtual functions but non-virtual destructor
myICalc.h:25: warning: ‘class myICalc’ has virtual functions but non-virtual destructor
c++ -g -Wall -fno-rtti -fno-exceptions -shared -L/usr/lib/xulrunner/sdk/lib -o myCalc.so myCalc.o -lxpcomglue -lnspr4 -lplds4

これでcomponents/myCalc.soができる。

でも、まだこれだけじゃだめ。

XPCOMの登録 編集

↑で作った共有ライブラリが読み込まれたときに、中に入っている XPCOMを登録する機能が必要になる。その機能を components/myCalcModule.cppとして実装する。

components/myCalcModule.cpp:

#include "nsIGenericFactory.h"
#include "myCalc.h"

NS_GENERIC_FACTORY_CONSTRUCTOR(myCalc)

static nsModuleComponentInfo components[] =
{
    {
       MY_CALC_CLASS_NAME,
       MY_CALC_CID,
       MY_CALC_CONTRACT_ID,
       myCalcConstructor,
    }
};

NS_IMPL_NSGETMODULE("myCalcModule", components)

また、components/MakefileのOBJSにも加えておく。

components/Makefile:

...
OBJS = myCalc.o myCalcModule.o
...

今回はmyCalcのみ登録しているが、複数のXPCOM(オブジェクトって いった方がいい?)を一つの共有ライブラリに入れて、まとめて登 録することもできる。たぶん。試していないけど。

いつものようにdist.shでコンパイルし、.xpiを更新し、再インストー ル。

% ./dist.sh
...
% iceweasel xpcom-sample-0.1.xpi

myCalcが登録されているかどうかは以下のようにして確認できる。

% grep myCalc ~/.mozilla/firefox/*/compreg.dat

以下のようなのがでればOK。UUIDがmyCalc.hに書いたものと同じも のであることを確認する。

abs:/.../xpcom-sample@cozmixng.org/components/myCalc.so,1173322260000
{8931dfd3-edf3-4b7d-bd44-1da72064f0dc},,,,abs:/.../myCalc.so
テスト用インターフェイスの追加 編集

対話型でJavaScriptの式を評価するインターフェイスがあればいい んだけど、あるかどうかわからない(エラーコンソールは毎回評価 コンテキストが違うみたいだからダメ)ので、作ったXPCOMを使うテ スト用のインターフェイスを作る。メニューバーにメニューを追加 し、myCalc.addを使って3 + 4を実行するJavaScriptを実行するよう にする。

content/overlay.xul:

<?xml version="1.0"?>
<overlay
  id="test-overlay"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <menubar id="main-menubar">
    <menu label="XPCOM sample">
    <menupopup>
      <menuitem label="Call sample XPCOM"
        oncommand="
(function () {
var obj;
try {
  const cid = '@cozmixng.org/xpcom-sample/Calc;1';
  obj = Components.classes[cid].createInstance();
  obj = obj.QueryInterface(Components.interfaces.myICalc);
} catch (err) {
  alert(err);
  return;
}
alert('3 + 4 = ' + obj.add(3, 4));
})();
"/>
      </menupopup>
    </menu>
  </menubar>
</overlay>

.xpiを更新し、再インストールする。

% ./dist.sh
% iceweasel xpcom-sample-0.1.xpi

「XPCOM sample」→「Call sample XPCOM」を実行して 「3 + 4 = 7」というアラートウィンドウがでたら成功。

C++のXPCOM on Mac OS X 編集

↑の続き。

ソースはここ

PPC版でもIntel版でも動くユニバーサルバイナリ(?)を作る。

必要なもの 編集
  • Xcode 2.4.1(使ったのが2.4.1ってだけ)
  • Mac OS X 10.4.8(使ったのが10.4.8ってだけ)
  • Firefox本体
  • gecko-sdk
ビルドスクリプトの更新 編集

Mac OS Xでは、GCCではなくてXcodeを使ってコンパイルする。その ため、Linux用のMakefileは使用できない。また、それに対応するた めにdist.shを変更する必要がある。

Xcodeのプロジェクトはcomponents/myCalc.xcodeproj/に配置するこ とにする。

dist.sh:

#!/bin/sh

cd `dirname $0`

if [ -x "`which gnused`" ]; then
    SED=gnused
else
    SED=sed
fi

#basename=`basename $PWD`
basename=xpcom-sample
version=`grep '<em:version>' install.rdf | $SED -e 's,</\?em:version>,,g'`
version=`echo $version | $SED -e 's/[[:space:]]//g'`

xpi=$basename-$version.xpi

case `uname` in
    Linux)
	(cd components && make) || exit 1
	component_shared="components/myCalc.so"
	;;
    Darwin)
	build_type=Release
	xcodebuild_args="-project myCalc.xcodeproj -configuration $build_type"
	(cd components && xcodebuild $xcodebuild_args) || exit 1
	component_shared="components/libmyCalc.dylib"
	cp components/build/$build_type/libmyCalc.dylib $component_shared
	;;
    *)
	echo "Unknown environment"
	exit 1
	;;
esac

component_xpt="components/myICalc.xpt"
components="$component_xpt $component_shared"

xpi_contents="content $components chrome.manifest install.rdf"

rm -f $xpi
zip -q -r -9 $xpi $xpi_contents -x \*/.svn/\* || exit 1
.xptと.hの生成 編集

Mac用のgecko-sdkに入っているxpidlは古いglibとlibIDLでコンパイ ルされている。これは以下のようにすれば確認できる。

 % otool -L gecko-sdk/bin/xpidl
 gecko-sdk/bin/xpidl:
	  /sw/lib/libglib-1.2.0.dylib (compatibility version 1.0.0, current version 1.10.0)
	  /sw/lib/libIDL-0.6.0.dylib (compatibility version 5.0.0, current version 5.4.0)
	  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 71.1.4)

このくらいのバージョンのやつは最近のFinkとかMacPortsとかでは 入手困難。なので、Mac OS Xでは.idlから.xptと.hを生成するのは 諦めよう。Linuxとかで生成した.xptと.hを持ってきましょう。

あるいは、 xpidl実行Webサービスを 利用する。詳しい使いかたは xpidl.cgiの使いかた を参照。

Xcodeプロジェクトの作成 編集
  1. ファイル→新規プロジェクト
  2. 空のプロジェクト
    1. プロジェクト名: myCalc
    2. ディレクトリ: .../xpcom-sample/components/
  3. 左ペインのmyCalcってとこで右クリック
    1. 追加→新規ターゲット
    2. BSD/Dynamic Library
      1. ターゲット名:myCalc
  4. 「ターゲットmyCalcの情報」とかいうウィンドウがでるので消す
  5. 左ペインのmyCalcってとこで右クリック
    1. 追加→既存のファイル
    2. myCalc.cpp, myCalc.h myCalcModule.cpp, myCalc.hを選択してまとめて追加
    3. プロンプトがでたらデフォルトのまま追加(ターゲットに追加でさっき作ったmyCalcにチェックが入っていることを確認)
  6. 左ペインのmyCalcってとこでダブルクリック
    1. 「プロジェクトmyCalcの情報」とかいうウィンドウがでる
    2. 「一般」タブ→「ターゲットSDKを使用したクロス開発」: 「Mac OS X 10.4 (Universal)」
    3. 「ビルド」タブ→「構成」: 「全ての構成」
    4. 「アーキテクチャ」→下のほうにある「編集」ボタン: 「PowerPC」と「Intel」にチェック
    5. 「ヘッダ検索パス」→下のほうにある「編集」ボタン: 下にある「+」ボタンを押して項目を増やし、gecko-sdk/includeへパスを通す
      1. 相対パスにする場合はソース中ではcomponents/ディレクトリから指定
      2. サンプルソース中ではトップディレクトリ(xpcom-sample)と同じディレクトリにgecko-sdkが展開されていると仮定している
    6. 「ライブラリ検索パス」→下のほうにある「編集」ボタン: 下にある「+」ボタンを押して項目を増やし、Firefox.app/Contents/MacOSへパスを通す
      1. サンプルソース中では/Applications/以下にFirefox.appがインストールされていると仮定している
    7. 「他のリンカオプション」→下のほうにある「編集」ボタン: 下にある「+」ボタンを5回押して項目を増やし、それぞれ「-lxpcom_core」、「-lxpcom」、「-lnspr4」、「-lplds4」、「-lplc4」を追加
  7. メニューから「ビルド」→「全てのターゲットをクリーニング」
  8. メニューから「ビルド」→「ビルド」
  9. メインウィンドウの左ペインの「エラーと警告」を見て警告・エラーが出ていないことを確認
インストール 編集

いつものようにdist.shを実行して.xpiを作成する。

% ./dist.sh

インストールするにはできたxpcom-sample-0.1.xpiをFirefoxにドラッ グする。うまくインストールされていればメニューに「XPCOM sample」がでて、「Call sample XPCOM」をやって「3 + 4 = 7」と いう警告ウィンドウが出れば成功。

コマンドラインから確認するにはLinuxと同じようにこんな感じ。

% grep myICalc ~/Library/Application\ Support/Firefox/Profiles/*/xpti.dat

こんなのがでてくれば.xptのインストールは成功している。

142,myICalc.xpt,6,134,1173341340000
1294,myICalc,{c95498ae-16f5-4b46-8713-2cf79e30d4ef},142,-1,1

XPCOMがインストールされているかはこう。

% grep myCalc ~/Library/Application\ Support/Firefox/Profiles/*/compreg.dat

こんなのがでてくればOK。

abs:/.../xpcom-sample@cozmixng.org/components/libmyCalc.dylib,1173345060000
{8931dfd3-edf3-4b7d-bd44-1da72064f0dc},,,,abs:/.../libmyCalc.dylib

C++のXPCOM on Windows 編集

↑の続き。

ソースはやっぱりここ

Microsoft Visual Studio 8で作る。CランタイムDLL(MSVCR80.dll)がない環境でも動くようにする。

必要なもの 編集
  • Microsoft Visual Studio 8
  • Windows XP
  • Cygwin: dist.shとかgrepとかを使わないならいらない。
  • gecko-sdk
ビルドスクリプトの更新 編集

WindowsではXPCOMの拡張子が.soではなく.dllになる。また、Visual Studioでは Makefileではなくて、ソリューションファイルを使ってコンパイルする。それら に対応するためにdist.shを変更する必要がある。

Visual Stuido 8のソリューションファイルはcomponents/myCalc/myCalc.slnに 配置することにする。また、devenv.exe(Visual Studio 8のコマンド名)にパ スが通っていない場合はC:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exeにあると仮定する。

dist.sh:

#!/bin/sh

cd `dirname $0`

if [ -x "`which gnused 2>&1 /dev/null`" ]; then
    SED=gnused
else
    SED=sed
fi

#basename=`basename $PWD`
basename=xpcom-sample
version=`grep '<em:version>' install.rdf | $SED -e 's,</\?em:version>,,g'`
version=`echo $version | $SED -e 's/[[:space:]]//g'`

xpi=$basename-$version.xpi

case `uname` in
    Linux)
        (cd components && make) || exit 1
        component_shared="components/myCalc.so"
        ;;
    Darwin)
        build_type=Release
        xcodebuild_args="-project myCalc.xcodeproj -configuration $build_type"
        (cd components && xcodebuild $xcodebuild_args) || exit 1
        component_shared="components/libmyCalc.dylib"
        cp components/build/$build_type/libmyCalc.dylib $component_shared
        ;;
    CYGWIN*)
        build_type=Release
        if which devenv > /dev/null; then
            DEVENV="devenv"
        else
            DEVENV="/cygdrive/c/Program Files/Microsoft Visual Studio 8/Common7/IDE/devenv.exe"
        fi
        "$DEVENV" /Build $build_type components/myCalc/myCalc.sln || exit 1
        component_shared="components/myCalc.dll"
        cp components/myCalc/$build_type/myCalc.dll $component_shared
        ;;
    *)
        echo "Unknown environment"
        exit 1
        ;;
esac

component_xpt="components/myICalc.xpt"
components="$component_xpt $component_shared"

xpi_contents="content $components chrome.manifest install.rdf"

rm -f $xpi
zip -q -r -9 $xpi $xpi_contents -x \*/.svn/\* || exit 1
.xptと.hの生成 編集

Windows用のgecko-sdkに入っているxpidlは古いglibとlibIDLでコンパイルされ ている。これは以下のようにすれば確認できる。

% objdump -p ../gecko-sdk/bin/xpidl.exe | grep -i dll
DllCharacteristics      00000000
 vma:            Hint    Time      Forward  DLL       First
        DLL Name: libIDL-0.6.dll
        DLL Name: glib-1.2.dll
        DLL Name: MSVCRT.dll

このくらいのバージョンのやつをインストールするくらいなら スタティックリンクされたxpidl を拾ってくるか、あきらめてLinuxとかで生成した.xptと.hを持ってきた方がい いでしょう。

あるいは、 xpidl実行Webサービスを 利用する。詳しい使いかたは xpidl.cgiの使いかた を参照。

xpidlのオプションはLinuxと同じなので省略。

Visual Studioソリューションの作成 編集
  1. ファイル→新規作成→プロジェクト
  2. Visual C++→全般→空のプロジェクト
    1. プロジェクト名: myCalc
    2. 場所: .../xpcom-sample/components/
    3. ソリューションのディレクトリを作成: チェックをはずす
  3. 完了
  4. 左ペインのmyCalc→ソースファイルで右クリック
    1. 追加→既存の項目→上のフォルダにいってmyCalc.cppとmyCalcModule.cppを選択→追加
  5. 左ペインのmyCalc→ヘッダーファイルで右クリック
    1. 追加→既存の項目→上のフォルダにいってmyCalc.hとmyICalc.hを選択→追加
  6. プロジェクト→myCalcのプロパティ
    1. 左上のドロップダウンリストの構成: すべての構成
    2. 構成プロパティ→全般→構成の種類
      1. ダイナミック ライブラリ (.dll)
    3. 構成プロパティ→C/C++→全般→追加のインクルードディレクトリ
      1. ..\..\..\gecko-sdk\include(xpcom-sampleと同じレベルにgecko-sdkがあるとする)
    4. 構成プロパティ→リンカ→全般→追加のライブラリディレクトリ
      1. ..\..\..\gecko-sdk\lib(xpcom-sampleと同じレベルにgecko-sdkがあるとする)
    5. 構成プロパティ→リンカ→入力→追加の依存ファイル
      1. xpcomglue_s.lib xpcom.lib nspr4.lib
      2. 構成をRleaseにしてlibcmt.libも追加
      3. 構成をすべての構成に戻す
    6. 構成プロパティ→リンカ→入力→特定のライブラリの無視
      1. MSVCRT
    7. 構成プロパティ→リンカ→マニフェスト→マニフェストの生成
      1. いいえ
インストール 編集

いつものようにdist.shを実行して.xpiを作成する。

% ./dist.sh

インストールするにはできたxpcom-sample-0.1.xpiをFirefoxにドラッ グする。うまくインストールされていればメニューに「XPCOM sample」がでて、「Call sample XPCOM」をやって「3 + 4 = 7」と いう警告ウィンドウが出れば成功。

コマンドラインから確認するにはLinuxと同じようにこんな感じ。

% grep myICalc /cygdrive/c/Documents\ and\ Settings/$USER/Application\ Data/Mozilla/Firefox/Profiles/*/xpti.dat

こんなのがでてくれば.xptのインストールは成功している。

4,myICalc.xpt,3,134,1173668700000
587,myICalc,{c95498ae-16f5-4b46-8713-2cf79e30d4ef},4,-1,1

XPCOMがインストールされているかはこう。

% grep myCalc /cygdrive/c/Documents\ and\ Settings/$USER/Application\ Data/Mozilla/Firefox/Profiles/*/compreg.dat

こんなのがでてくればOK。

abs:C:\...\xpcom-sample@cozmixng.org\components\myCalc.dll,1173763800000
{8931dfd3-edf3-4b7d-bd44-1da72064f0dc},,,,abs:C:\...\myCalc.dll

コメント 編集