C++でGoogle Chromeのプラグインを書いてみた

はじめに

Google Chromeプラグインを書くには、NPAPIを使用する必要があるあるけど、サンプルプログラムが少ないから勉強するのに敷居が高い。そこで、Nixysaを使うと簡単にプラグインを作成できる。
今回作ったコード
https://github.com/nus/NPAPISample
参考にしたサイト
http://code.google.com/p/nixysa/wiki/HelloWorldWalkThru

Nixysaとは

C++のコードからNPAPIを生成させるツール。
http://code.google.com/p/nixysa/

NPAPIで出来ること

開発環境

サンプルプラグインの動作

四則演算を行うプラグインを作る。
C++のコードに起こすとこんな感じ。

class Calcurator {
float add(float a, float b) {return a + b;}
float sub(float a, float b) {return a - b;}
float mul(float a, float b) {return a * b;}
float div(float a, float b) {return a / b;}
};

これをNixysaでNPAPIのコードを生成させる。

開発の流れ

  1. Nixysaのダウンロード
  2. Nixysaに必要なファイルを書く
  3. Visual C++でプロジェクトファイルの作成
  4. NixysaでNPAPIのソースコードを生成
  5. 生成されたファイルをプロジェクトに追加しビルド
  6. Google Chromeプラグインをインストール

1.Nixysaのダウンロード

svn checkout http://nixysa.googlecode.com/svn/trunk/ nixysa-read-only

作業フォルダをnixysa-read-onlyとする

2.クラスを書く

nixysa-read-only
├─NPAPISample
      calculator.cc
      calculator.h
      calculator.idl
      calculatorplugin.cc

宣言
https://github.com/nus/NPAPISample/blob/master/calculator.h
定義
https://github.com/nus/NPAPISample/blob/master/calculator.cc
クラスの構成をIDLファイルで書く
https://github.com/nus/NPAPISample/blob/master/calculator.idl
プラグインの概要を書く
https://github.com/nus/NPAPISample/blob/master/calculatorplugin.cc

3.Visual C++でプロジェクトファイルの作成

メニューバー -> ファイル -> 新規作成 -> 既存のコードからのプロジェクトを作成
既存のコードからのプロジェクトを作成ダイアログが出る
[次へ]

「プロジェクトファイルの場所」はコードの作成場所を指定
「プロジェクト名」をここでは、calculatorとした。


「プロジェクトの種類」を[ダイナミックリンクライブラリ(DLL)プロジェクト]を指定
[次へ]

プリプロセッサの定義」に「OS_WINDOWS」を追加
[次へ]
[完了]
calculatorプロジェクトのプロパティで[構成プロパテ] -> [C/C++] -> [全般]の「追加のインクルードディレクトリ」に

.;..\nixysa\static_glue\npapi;.\glue;..\third_party\npapi\include;%(AdditionalIncludeDirectories)

と入力
[OK]

4.NixysaでNPAPIのソースコードを生成

calculator.idlのプロパティで「項目の種類」を「カスタム ビルドツール」に変更
[OK]を押し、再度、calculator.idlのプロパティを開く
[構成プロパティ] -> [カスタム ビルドツール] の「コマンドライン」に

$(ProjectDir)\..\nixysa\codegen.bat --output-dir=glue --generate=npapi --force %(Filename)%(Extension)

「出力ファイル」に

glue\%(Filename)_glue.cc;glue\%(Filename)_glue.h;glue\globals_glue.cc;glue\globals_glue.h;glue\hash;%(Outputs)

を書く


calculator.idlのみコンパイル

すると、nixysa-read-only\NPAPISample\glueフォルダにソースコードが生成される。これが、NixysaでNPAPIのコードを出力したもの

5.生成されたファイルをプロジェクトに追加しビルド

プロジェクトにファイルを追加

nixysa-read-only\NPAPISample\glue\
 +calculator_glue.cc  calculator_glue.h  globals_glue.cc  globals_glue.h

nixysa-read-only\nixysa\static_glue\npapi
 +common.cc  main.cc  npn_api.h  static_object.cc  common.h   npn_api.cc  plugin_main.h  static_object.h

nixysa-read-only\examples\complexフォルダの

complex.rc  complex.def

をnixysa-read-only\NPAPISampleにコピーし、この2うつのファイル名を

calculator.rc  calculator.def

に変更する。
次に中身を編集
calculator.rcファイルの70行目に

VALUE "FileExtents", ""

を追加
プラグイン名に合わせて他の行も編集
編集し終えたファイル
https://github.com/nus/NPAPISample/blob/master/calculator.def
https://github.com/nus/NPAPISample/blob/master/calculator.rc

プロジェクトファイルのプロパティで[構成プロパティ] -> [リンカー] -> [入力] の「モジュール定義ファイル」の欄に
「calculator.def」を入力

6.生成されたファイルをプロジェクトに追加しビルド

プロジェクトのビルドをすると、calculator.dllが生成される。
これが、プラグイン

6.1 ビルドエラーの対処方法

もし、下記の様なビルドエラーが起きたら

1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(6361): error C2146: 構文エラー : ';' が、識別子 'ContextRecord' の前に必要です。
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(6361): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(6361): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(12983): error C2065: 'PCONTEXT' : 定義されていない識別子です。
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(12984): error C2146: 構文エラー : ')' が、識別子 'ContextRecord' の前に必要です。
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(12984): warning C4229: 旧形式が使用されています : データの修飾子は無視されます。
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(12984): error C2182: 'RtlCaptureContext' : 'void' 型が不適切に使用されています。
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(12984): error C2491: 'RtlCaptureContext' : dllimport データ の定義は許されません。
1>C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\winnt.h(12984): error C2059: 構文エラー : ')'
以下同様なエラー ...

nixysa-read-only\third_party\npapi\include\nptypes.hの48行目に1行追加

47 #if defined(WIN32) || defined(OS2)
48     #include <Windows.h> // この行を追加

nixysa-read-only\nixysa\static_glue\npapi\npn_api.hの107,108行目の

107 size_t size = std::min(sizeof(g_browser_functions),
108                        static_cast<size_t>(funcs->size));

107 size_t size;
108 {
109     using namespace std;
110    size = min(sizeof(g_browser_functions),
111                      static_cast<size_t>(funcs->size));
112 };

に変更

終りに

以上がプラグインの製作過程
後は、Google ChromeなりFirefox拡張機能の作り方に従い、プラグインを読み込ませる。