SyntaxHighlighter

2011年11月27日日曜日

NPAPI プラグインの作り方 for Windows その3

NPAPI プラグインの作り方 for Windows その3

続きです。

今回は、サンプルをビルドできるようにします。

ファイルの準備

前回の説明の中で書いたように、Gecko SDK 1.9.2と、バージョン 1.9.2 向けのnpruntime のサンプルをダウンロードします。

Gecko SDK は、展開して得られるincludeディレクトリ以下のみを使います。

面倒な人向けに、GitHubにまとめておいたので、そちらのoriginal_filesディレクトリ以下をお使いください。

以降では、これらをC:\work\test\includeおよびC:\work\test\npruntime以下に展開したとして話を進めます。

Visual Studio プロジェクトの作成

続いて、Visual Studio のプロジェクトを作成します。

Compiling The npruntime Sample Plugin in Visual Studioのページを参考に進めます。

プロジェクトの新規作成

以下のような設定で、新しいプロジェクトを作成します。

  1. メニューから「ファイル」-「新しいプロジェクト」を選びます。
  2. 種類は「Win32」の「Win32プロジェクト」を選びます。
  3. 「npsample」などの適当な名前をつけて、プロジェクトを作成します。
  4. ウィザード中の「アプリケーションの設定」で「DLL」を選び、「空のプロジェクト」にチェックを入れます。

ファイルの追加

サンプルファイルをプロジェクトに追加します。

ダウンロードしてあるC:\work\test\npruntime以下のファイルを、作成したプロジェクトのディレクトリにコピーしておくとよいでしょう。

  1. ソリューションエクスプローラーの「ソースファイル」を右クリックし、「追加」-「既存の項目」をクリックします。表示されたダイアログで、np_entry.cpp, npn_gate.cpp, npp_gate.cpp, plugin.cppを追加します。
  2. 同様に「ヘッダファイル」を右クリックし、plugin.h, resource.hを追加します。
  3. さらに「リソースファイル」を右クリックし、nprt.rcを追加します。

これで、図のような状態になっているはずです。

プロジェクトの設定

続いて、プロジェクトの設定をします。

  1. メニュー「プロジェクト」から「XXX のプロパティ」(XXX はプロジェクト名) をクリックし、プロパティを表示します。
  2. 左上の「構成」で Release を選択します。
  3. 「構成プロパティ」の「全般」の「ターゲット名」を、作成するプラグインの名前に設定します。これは、プロジェクト名と異なる名前を付ける場合には必須です。NPAPI プラグインの名前は、np*.dllという形式であるのが正しいようなので、プロジェクト名がそうなっていない場合は、ここで名前を設定します。
  4. 「構成プロパティ」の「全般」の「文字セット」を「マルチバイト文字セットを使用する」に設定します。
  5. 「構成プロパティ」の「C/C++」の「追加のインクルードディレクトリ」に、ダウンロードしておいた Gecko SDK のインクルードディレクトリである「C:\work\test\include」を追加します。
  6. 「構成プロパティの」の「C/C++」の「プリプロセッサ」の「プリプロセッサ定義」に、以下をすべて改行で区切って追加します。

    WIN32, _WINDOWS, XP_WIN32, MOZILLA_STRICT_API, XPCOM_GLUE, XP_WIN, _X86_

  7. 「構成プロパティの」の「リンカー」の「入力」の「モジュール定義ファイル」をnprt.defに設定します。nprt.defのフルパスを設定してください。

ファイルの修正

ビルド対象を「Debug」から「Release」に変更し、ビルドしてみると、いくつか警告やエラーが出ます。ここでは、その対応をします。

  1. まず、コンパイルエラーの一つ目であるplugin.cppprintfをすべて削除します。

    手作業で消してもよいですが、エディタなどで「printf」を「//printf」に置換すると楽だと思います。

  2. 続いて、strdupは ISO 標準の_strdupにするべきだ、という警告が出ているので、これもstrdup_strdupに置換することで対応しておきます。
  3. また、strcpyはセキュアではない、という警告については、対応が面倒なので、「プリプロセッサ定義」に_CRT_SECURE_NO_WARNINGSを定義リストに加えることで消してしまうことにします。
  4. nprt.defの一行目のLIBRARYの右に書かれた単語NPRTは、このプラグインの名前です。この名前が「構成プロパティ」で設定したものと異なる場合、警告が出るので、こちらも「構成プロパティ」で設定したものと同じ名前に設定します。
  5. 最後に、nprt.rc#include "afxres.h"#include "windows.h"に変更します。

これで、ひとまずビルドはでき、DLL ファイルが生成されるようになったと思います。

ここまでで、ひとまずプラグインとなる DLL のビルドができました。

しかし、このままではソースコードのバグにより、うまく動作しません

次回は、正しく動作するように修正していきます。

2011年11月21日月曜日

NPAPI プラグインの作り方 for Windows その2

NPAPI プラグインの作り方 for Windows その2

前回の続きです。

詳しい説明に入る前に

最初にことわっておきますが、NPAPI はこれから廃れゆく運命にあるだろう技術です。

今後は、Google が強力に推進する Native Client や、それと絡んだ NPAPI の置き換え規格となる PPAPI が主流になっていくだろうと思います。

ただし、これらの技術はまだ Hot すぎるので、今後まだまだ仕様が変わっていくだろうと思います。(私もまだそれほどきちんと調べていません。)

そういった事情から、まだもう少しは既存の技術である NPAPI を使わざるを得ない状況が続くのではないかと思っています。

サンプルとして作成するもの

何か目的があった方が説明しやすいので、サンプルとして「ローカルディスクの空き容量を返す」プラグインを作成することにします。

こういったことが現在の Native Client などで可能なのかよく分かりませんが、ひとまず HTML5 の範疇だけでは実現が不可能そうなことをやってみます。

NPAPI プラグインを作成するために必要なもの

以下のものが必要です。

開発環境: Visual C++ 2010 Express Edition

Visual C++ 2010 Express Editionが無料で入手できるのでよいと思います。試してはいませんが、VC++ 2005, 2008 でも問題なくコンパイルできると思います。

Gecko SDK 1.9.2

NPAPI プラグインを作成するには、Gecko SDK に含まれている include ファイルが必要です。 今回は、Gecko SDK 1.9.2を用いることにします。

npruntime のサンプル

今回作成するのは、NPAPI の中でも、WEB ページの JavaScript からプラグインのメソッドを呼ぶことができる NPRuntime という仕様に従ったものです。 スクラッチから書くのは大変なので、このサンプルコードをベースに進めることにします。 偉そうに書いていますが、私自身はそれほどきちんと NPAPI や NPRuntime の詳細を分かっていません。

ちなみに、私はnpruntime のサンプルのページにあるファイルをまとめてダウンロードする方法がよく分からなかったので、一つ一つ選んで、開いたページに出てくる "Raw File" のリンクからダウンロードしました。

これで、作成の準備は整いました。

次回は、サンプルの修正とビルドおよびテストをしてみます。

続く。

2011年11月16日水曜日

NPAPI プラグインの作り方 for Windows その1

NPAPI プラグインの作り方 for Windows その1

今回から何回かにわたって、NPAPI プラグインの作り方についてまとめておこうと思います。

ただし、私がまだ細かいところまで理解できているわけではないので、間違いなどがあるかもしれません。ご了承ください。

また、あくまで Windows 版の NPAPI についての記述です。

NPAPI プラグインとは

NPAPI とは、Wikipedia の解説ページにもあるように、Netscape Plugin Application Programming Interfaceの略です。

よく Firefox のアドオンや、Google Chrome の拡張機能と混同されることがありますが、ここで触れる NPAPI プラグインは、これらとは異なります。

例えば FLASH 動画を表示し再生するための Adobe Flash Plugin や、PDF ファイルをブラウザ内で表示できるようにする Adobe Reader Plugin などのことです。

NPAPI とは、このプラグインの仕様を定めたものであり、プラグインを開発するには、ある程度は NPAPI の仕様を知る必要があります。

NPAPI プラグインでできること

基本的に、NPAPI プラグインでは何でもできます。

そのため、Google Chrome の拡張機能では、通常は実現不可能な「ローカルファイルを検索する」や「ローカルのプログラムを直接起動させる」などを行うことも可能となります。

また、ブラウザ上に表示を行うタイプのものでは、Windows の場合はウィンドウのハンドルを取得できるので、完全に自由に描画を行うこともできます。

続く。

2011年11月15日火曜日

requireとrequire_dependencyとRuby 1.8.7とRuby 1.9.2

requirerequire_dependencyと Ruby 1.8.7 と Ruby 1.9.2

先日、Redmineの Version 1.2.2 もリリースされたので、プラグインを書くときに気になった、requirerequire_dependencyの違いおよびRuby のバージョンによるrequireの挙動の違いについて書こうと思います。

とは言っても、よく書かれている「カレントディレクトリがロードパスに含まれなくなった」ということではありません。

なお、これは Rails 2.3.11, 3.1.0 を見て書いています。また、Redmine は Version 1.2.2 を見ながら書いています。

requirerequire_dependency

Rails のコードを見たことがある人は分かると思いますが、Rails のコードではrequireの代わりにrequire_dependencyが使われていることに気付くと思います。

それぞれ簡単にまとめると以下のようになります。

require
Ruby の組込み関数。正確には、Kernelモジュールのメソッド。
引数で渡された .rb ファイルなどを読み込む。ただし、既に読み込み済みのファイルは読み込まない。
読み込まれたモジュールは$", $LOADED_FEATURESに格納されて管理される。
require_dependency
Rails が定義した独自のメソッド。activesupport/lib/active_support/dependencies.rbで定義されている。
引数で渡された .rb ファイルなどを読み込む。ただし、既に読み込み済みのファイルは読み込まない。development モードで実行している場合はloadを使って読み込まれる。production モードで実行している場合は、requireを使って読み込まれる。
これは、development モードで実行している場合は、動的にファイルを何度も読み込む必要があるため。

Redmine プラグインで注意すること

結論から書くと、Redmine プラグインの中では、Redmine のモデル、ビュー、コントローラー、ヘルパーを読み込むには、require_dependencyを使うべしということです。

ここで、requireを使うと失敗します。

上の説明で書いたように、production モードで実行するならどちらでも結局requireが呼ばれるので変わらない、と思うかもしれませんが、そうではありません。

以下で順に説明します。

Ruby 1.8.7 と Ruby 1.9.2 でのrequireの挙動の違い

まず、requireの挙動をもう少し詳しく見てみます。

Ruby 1.8.7 でのrequireの挙動

main.rbから、required.rbを、下記のようにrequireする場合を考えます。

ここでmain.rbを実行すると、出力は下記のようになり、二回目のrequireではrequired.rbがロードされていないことが分かります。

これは当然の挙動だと思います。

次に、以下のように、相対パスや絶対パスを指定してrequired.rbを読み込んでみます。

出力は以下のようになります。

このように、予想に反して (かどうかは分かりませんが) 三回とも読み込まれています。

Ruby 1.9.2 でのrequireの挙動

一方で、同じコードを Ruby 1.9.2 で実行してみます。

ただし、Ruby 1.9.2 では、カレントディレクトリがロードパスに含まれなくなっているので、先頭で追加してやった状態で実行してみます。

出力は以下のようになります。

今回は、一度しか読み込まれませんでした。

このように、Ruby のバージョンによってrequireの挙動は微妙に異なります。

Ruby 自体のソースを見れば分かりますが、「既に読み込まれたか」を表すリストである$", $LOADED_FEATURESに記憶する方法が、Ruby 1.8.7 と Ruby 1.9.2 では異なるようです。

Ruby 1.8.7 では指定されたファイルをそのままの形で$LOADED_FEATURESに覚えておきます。 そのため、require("required")require("./required")など、指定方法が異なると、複数回ロードされることとなります。

一方で、Ruby 1.9.2 では、常に絶対パスに直して覚えるようになっています。 その結果、実際に同じファイルであれば、指定方法が異なっても複数回ロードされることはありません。

Redmine プラグインでrequire_dependencyを使わないと正しく動作しない理由

以上を踏まえて、なぜ production モードであっても Redmine プラグインでrequire_dependencyを使わないとうまく動作しないのか、について書きます。

Redmine は、現在も Ruby 1.8.7 で動作しています。

そのため、あるファイルをrequireする際に、絶対パスで指定した箇所とファイル名だけを指定した箇所がある場合、そのファイルは二重にロードされることになります。

一方で、require_dependencyでは、コードを追うと分かりますが、最終的に引数のファイル名を絶対パスに展開してからrequireもしくはloadします。

ここで、以下のように書いてしまった場合を考えてみます。

この例では、ApplicationHelperモジュールのformat_activity_titleメソッドを上書きしています。

しかし、このファイルとは別のファイルでrequire_dependency("application_helper")と書かれていると、そちらではapplication_helperが絶対パスに展開されてから、requireに渡されることになります。

そのため、ファイル名だけを指定してrequire("application_helper")としたときとは別のファイルとして扱われてしまい、別途、application_helper.rbがロードされることになります。

その結果、せっかく上書きしたメソッドが再度上書きされてしまい、変更が反映されなかったように見えてしまいます。

というわけで、素直にrequire_dependencyを使うようにするのがよいと思います。

2011年11月12日土曜日

C++11 に合った書き方 その2

C++11 に合った書き方 その2

昨日の続きです。C++11 らしい書き方のページについて、気になるものを中心に書いていきます。

C++11 らしい書き方とは

スマートポインタを使え

スマートポインタを積極的に使え、ということのようです。

これまでにも、auto_ptrがありました

しかし、このauto_ptrは非推奨となり、代わりにunique_ptrを使えとのことらしいです。

私は、関数内部でnewしたインスタンスをauto_ptrにくるんで返り値として返す、ぐらいしかauto_ptrを使っていませんでしたが、そういった場合は、auto_ptrのムーブセマンティック考慮版とも言えるunique_ptrの出番のようです。

その他には、既に多くの処理系で実装されているshared_ptrなどが標準として入るようになりました。

これまでにも使っていましたが、仕事で使う際に、「仕様に入っているから」と堂々と使えるようになるのはありがたいことです。

nullptr

これは、単純に0でもNULLでもなく、新予約語のnullptrを使いましょう、ということです。

C++ では、C言語と異なり、void *を任意の型のポインタに代入することができません。例えば、以下のようにNULLを定義していると、C++ ではコンパイルエラーとなります。

そのため、基本的にNULLは、単なる 0 と定義されています。

C++ では 0 は特殊な扱いをうけており、何も指さないポインタの値として、任意の型のポインタに代入することができると定められています。

一方で、0 は整数値なので、NULLを 0 と定義した場合、以下のようなオーバーロードされた関数がある場合に、多くのプログラマの直感と異なる挙動を示してしまいます。

このように、直感と異なり (1) が呼ばれてしまいます。

C++11 では、このような事態を避けるために、nullptrという新たな予約語を定義し、何も指さないポインタの値として使え、かつ整数として扱われないものが導入されました。

Uniform Initialization and Initializer Lists

ここに例として挙がっているものと同様な下記コードで、私も以前にとても困ったことを覚えています。

最初は (1) のようなコードを書いており、なぜコンパイルエラーになるのかがまったく分からず、ふとしたはずみで (2) のように書くとコンパイルが通ったことを覚えています。

C++11 では、{, }による初期化が可能になるので、これらを使うことで、上の例のような場合を避けることができるようです。

また時間があれば、しっかりと C++11 の勉強もしようと思います。

2011年11月10日木曜日

C++11 に合った書き方

C++11 に合った書き方

仕様の確定

C++0x と言われていた C++ の次期仕様が少し前に確定しました。

結局、紆余曲折を経たため、当初の予定だった 2009 年の間には確定させることができず、2011 年までずれこんでしまったようです。

私自身は、わりと C++ が好きな方なので、時々は新しい仕様をチェックしたりしていました。

個人的には、今回の仕様のうちでlambdaの導入やスマートポインタの充実、autoなど型推論の強化などが、特に嬉しいポイントです。

いずれも、これまでに不満を感じていた箇所でした。

Ruby をよく使うようになってから、特に型情報の記述量の多さには不満を感じていたので、型推論の強化は非常に歓迎しています。

C++11 らしい書き方とは

そんな新機能がいろいろと追加された C++ ですが、Elements of Modern C++ Styleに、今後、C++11 を使用していく上で推奨されるコーディングスタイルについて、まとめられていました。

順に見ていこうと思います。

auto

一つ目の例としては、以下のようなものが挙げられていました。

つまり、右辺を見ることで型がはっきりする場合は、省略してしまおうというのが基本スタンスのようです。

これまでは、インスタンスの動的生成などは、多態性を使わない場合には無駄そのものである以下のような書き方をしていました。

C# のvarを見るたびに、こういったものが C++ にもあればよいのにと思っていたので、これが正式仕様になったのは喜ばしいことです。

ただ、一方で、例の二番目のような場合については、好みが分かれるのではないかと思いました。

configの定義 (おそらくmapなど) を見れば、すぐにxlimitの型が分かるのですが、少なくともコードの一部分を見ている人間には、すぐには何か分かりません。

そういう意味で、関数の返り値などで変数を宣言と同時に初期化する場合には、autoを使うかどうかは難しいところだと思います。

おそらくは、STL のようなライブラに含まれるかどうかを基準とするのがよいのではないかと思います。広く知られたライブラリの関数であれば、返り値の型が判明しているので、変数の型を省略してautoにしてしまってもよいように思いました。

続く。

2011年11月9日水曜日

Open TortoiseSVN for Google Chrome™ のレビュー終了

Open TortoiseSVN for Google Chrome™ のレビュー終了

一週間ほどで、Google Chrome の拡張機能であるOpen TortoiseSVN for Google Chrome™のレビューが完了し、Chrome ウェブストアに並び始めました。

以前のブログの内容とも少し重なりますが、今回はそのプロセスについてまとめておこうと思います。

登録まで

登録するには、Google のアカウントが必要です。また、初回登録時には、5ドルを Google に支払う必要がありました。

他にも、アイコン、スクリーンショット、宣伝用のタイル画像などが必要です。

それぞれの画像やアイコンは、サイズや周囲の透明領域の幅などが決められているので、登録しようと思っている場合は、先に一度 Chrome ウェブストアのデベロッパーダッシュボードから必要なものを見ておいた方がよいと思いま。

また、タイトルに "Google Chrome" の文字列を入れる場合は、"XXX for Google Chrome™" の形式が推奨されているなど、いろいろ細かい規定があるので、登録の際に出るガイドラインを読んでおいた方がよいと思います。

また、多言語対応している場合は、各言語について説明を記述することができるので、それぞれについて忘れずに記入した方がよいでしょう。

私は、最初は英語の説明しか入力していないことに気付かず、公開されてからしばらくは、日本語の説明が空白のままになってしまっていました。

登録後

今回の拡張機能は、NPAPI を含んだものだったので、登録して「公開する」ボタンを押すと、「審査中」になりました。

一日か二日程度すると、Google の担当者の方から "Google Chrome Web Store Developer Agreement" という PDF の書類が送られてきます。

ざっと見たところ、悪意のあるツールを登録してはいけない、などの利用規約でした。

こちらにサインしたものをスキャナで取り込んで返信せよ、とのことなので、手書きのサインなどを記入した上でスキャンし、メールで返信しました。

レビューするためにはソースコードが必要だろうと思い、GitHubのアドレスをメールに書いておきました。これに関しては、必要だと言われたわけではないので、必須かどうかがよく分からないままです。

一週間程度すぎると、同じ担当者からメールが届き、「レビュー OK でした。30分以内に Chrome ウェブストアで見られるようになるよ」とのことだったので、すぐに見てみると、一般に公開されていました。

Firefox のレビューに比べ、レビュー対象者が少ないこともあるのでしょうが、かなりレビュー終了までの時間は短くてすみました。

また、レビュー自体も、それほどシステマティックに行われているようには見えず、私の場合は一人の担当者の方と、個別にメールのやりとりをした、という感じでした。

メール自体も、その方が手で書いているように見えました。

そんなわけで、無事に Chrome ウェブストアにて一般公開されました。よろしければお使いください。

また今度、使用方法や仕組みについてもきちんとまとめておこうと思います。

2011年11月7日月曜日

Redmine プラグイン その2

Redmine プラグイン その2

昨日の続きです。

Redmine プラグインの雛形の作成

Redmine のプラグインを作成するには、以下のようなコマンドを実行します。 Redmine 1.2.1 では、まだ Rails 2.3.X 系統なので、ruby script/generateでプラグインを作成します。

このコマンドにより、vendor/pluginsディレクトリの下にredmine_sample_pluginというディレクトリが作られ、プラグインの雛形が生成されます。

プラグインの仕組み

今回は、簡単のためにデータベースへの保存などは行わず、表示方法をカスタマイズしたり、機能を追加したりする場合について書きます。

init.rbからrequireする

この雛形に含まれるファイルで、最重要なものはinit.rbです。

このファイルは、Redmine が起動する際に自動で読み込まれます。

また、読み込まれる順序は、Redmine の Core ファイルが読み込まれた後です。

前回のオープンクラスの部分で書きましたが、この順序で読み込まれることが保証されているので、init.rbの中で Redmine 関係のクラス (例えばIssueクラス) を再定義することにより、自由にメソッドを追加、削除、上書きすることができます。

例えば、以下のように書いたファイルをlib以下に置き、init.rbからrequireすると、Issueクラスにopen?メソッドを追加することができます。 (ただし、後で書くように、普通はもう少し整理された定型の書き方があります。)

このように書いたファイルをinit.rbからrequireすることで、新たにIssueクラスに新しいメソッドを追加することができます。

重要なポイントは、Issueクラスという既存のクラスへの変更が、既存のファイルであるapp/models/issue.rbをまったく変更することなく可能となっている点です。

これは、Issueクラスのメソッドの全体が分かりにくいという大きな欠点もできますが、プラグインを配布する際に、特定のディレクトリにファイルを展開するだけでよいという、モジュールの可搬性という点において大きな利点を生むことになります。

実際のファイルは、以下のようにして、インスタンスメソッドやクラスメソッドを分離して記述することが多いです。

app以下で上書きする

これとは別に、appディレクトリ以下に直接ファイルを置くことによって、既定の動作を上書きして変更することもできます。

例えば、app/views/issues/_edit.rhtmlの内容を少し変更したものをvendor/plugins/redmine_sample_plugin/app/views/issues/_edit.rhtmlに置くことにより、もともとの_edit.rhtmlではなく、redmine_sample_plugin以下に置かれた_edit.rhtmlを使わせることができます。

これは、Rails がファイルを検索する順序として、各プラグインのapp以下を探し、見つからなければルートディレクトリ直下のappディレクトリを探すとなっているためです。

そのため、同名のファイルをプラグインのapp以下に同じディレクトリ構成で置いてやることにより、自由にデフォルトのファイルを置き換えることができます。

簡単に表示やデフォルトの挙動をカスタマイズする程度であれば、このあたりを理解するだけで比較的自由に変更することができると思います。

一方で、あまりに自由度が高いので、これをやりすぎると、全体の見通しが悪くなったり、他のプラグインとの関係で思わぬ副作用が出たりするかもしれません。

Rails は、そもそも組込みのクラスにもいろいろなメソッドを (勝手に) 追加しています。こういう部分は、きちんとした設計のもとに行えば、非常に使い勝手が上がりますが、下手に追加すると、混乱を招くだけです。

Rails では、きちんとした設計のもとに行うことで、利便性を実現しています。

それと同じように、プラグインに対してもユーザーが自由にカスタマイズできるようにしておき、「自己責任でプログラマが自由にしてね」という余地をあえて残すような設計にしているのかもしれません。

2011年11月6日日曜日

Redmine プラグイン

Redmine プラグイン

以前に Redmine プラグインの練習として作ってみたWiki GChart Formula Pluginの紹介をかねて、Redmine プラグインについて書きます。

オープンクラス

Redmine, Rails に限った話ではありませんが、Ruby のクラスは、オープンです。

Redmine や Rails のプラグインは、このオープンクラスの仕組みをうまく使っているので、今回はその説明を書くことにします。

「クラスがオープンである」というのは、例えば、一度クラスを定義した後からでも、自由にメソッドの追加や上書きなどができるということです。

例として、以下のような Ruby のプログラムを考えます。Testクラスが二回定義されていることに注意してください。

このスクリプトを実行すると以下のように出力されます。

old
new
ok

この例では、(1) で定義したメソッドprintが (4) で再定義され上書きされます。また、(5) で新しいメソッドprint2が新規に追加されています。

C# の部分クラス定義との違い

これは、C# の部分クラス定義の機能を使って、複数ファイルでクラスの各メソッドを定義できることと似た部分があります。

しかし、Ruby ではクラスの定義自体も通常のメソッド呼び出しなどと同じように実行時に行われる点が大きく違います。

C# などでは、定義自体が分割されていようがなかろうが、クラスの定義自体はコンパイル時に解釈され、実行時にクラスのメソッドが途中で動的に追加されたり置き換わったりすることはありません。

そのため、C# でもともと提供されている既存のクラスに対してメソッドを追加するようなことはできません。 また、(1), (4) のように同名のメソッドを定義することもできません。 というか、後から定義した方で上書きできたとしても、実行時にはその片方の定義しか使われないので、意味がありません。

一方で、Ruby ではそれらが可能です。

そのため、上に書いたコードは以下のように動きます。

  • (2) の段階では、まだ (4) の再定義がされていないので、(1) で定義された通りoldが出力されます。
  • (3) の段階では、まだ (5) の定義がされていないので、print2などというメソッドは存在せず、エラーになります。
  • (6) の段階では、(4) の再定義の後なので、newが出力されます。(1) で定義されていた、古いprintメソッドを呼ぶ方法はありません。
  • (7) の段階では、(5) の定義の後なので、okが出力されます。

このように、クラス定義も実行時に行われ、かつクラスがオープンであるために、後から既存クラスの挙動を変更することが非常に柔軟に行えます。

これらの挙動を利用することで、Redmine や Rails では、プラグイン側から Redmine や Rails のクラスを上書きすることにより、自由なカスタマイズをすることができます。

続く。

2011年11月5日土曜日

Blogger に変えてみました

Blogger に変えてみました

一昨日は FC2 で始めたのですが、諸事情により Blogger に変えてみました。

諸事情1: HTML5 に対応していた

FC2 はテンプレートを自由にカスタマイズできるのは嬉しいのですが、テンプレートの作者の力量次第で Valid でない HTML ファイルになってしまっているものが多いように思います。

Blogger は Google が管理しているだけあり、Google が推し進めている HTML5 に対応しています。

HTML5 には興味がありつつも、なかなか長い文章を書いたりしていないので、この機会に勉強しながら書き進めようと思います。

とは言いつつも、最初は<article>, </article>で囲むだけからスタートです。

諸事情2: Google のことが前より好きになった

11/1 の Google Developer Day に参加してから、以前よりも Google のことが好きになりました。

Google Labs などで、たくさん試してうまくいったものだけを残す、というようなやり方は、それほど好きにはなれないですが、個人や小規模なプログラマーにも等しくチャンスが行き渡るようなウェブストアの運営などは、どちらかというと好感が持てます。

諸事情3: あまり日本では使われていないと書いてあった

どこかのページに、まだあまり日本では使われていないと書いてあったので、よさそうな雰囲気を感じました。

Open TortoiseSVN for Google Chrome™ の登録

Open TortoiseSVN for Google Chrome™ の登録

これまでに Firefox のアドオンは作ったことがあったのですが、今回、初めて Google Chrome の拡張機能を作ってみました。

作成した拡張機能

すでに Firefox 版として作成し、公開しているOpen TortoiseSVNの Google Chrome 版を作ろうと思いました。

機能は、あらかじめ登録済みの URL をクリックしたときに、自動でローカルコンピュータの TortoiseSVN を起動してくれる、というものです。

Google Chrome 拡張機能の制約

Firefox のアドオンとは異なり、Google Chrome の拡張機能でできることは、非常に限られています。

Firefox では、XPCOM という OS 非依存なライブラリを介して様々なことができますが、Google Chrome では原則として HTML5 でできることしかできません。

今回は、「ローカルの TortoiseSVN を起動する」という、HTML5 の範疇を超えた動作をさせることが目的なので、NPAPIの助けを借りることになりました。

このあたりは、あまりまとまった日本語資料もなかったので、後日まとめようと思います。

Chrome ウェブストアへの登録

最終的に拡張機能ができあがったら、Chrome ウェブストアに登録します。

最初に、Google に対して 5ドルを支払わなければなりませんこれは、イタズラなどで登録されるのを防ぐためだそうです。

この点や、そのほかの手続きや準備に関しては、Firefox と比べると面倒に感じました。

私は別に売るのが目的ではないのでどうでもいいのですが、いろいろアイコンを作れだとか、一覧表示されるときの画像や使ったときの画面イメージを入れろなど、Chrome ウェブストアに登録するために必要なリソースファイルなどを要求されます。

最終的に登録が終わると、NPAPI を用いた拡張機能やローカルファイルにアクセスするものの場合、「審査待ち」になります。

登録してから次の日になると、「Google Chrome Web Store Developer Agreement」という PDF ファイルが送られてきて、サインして提出せよ、と言われました。

NPAPI プラグインを使うと、セキュリティ的に問題あることもできるためか、わりと厳重にしてあるように感じました。

いろいろ書き込んで返信し、あとは審査を待つばかりです。

ブログを始めてみました

ブログを始めてみました

プログラミングに関する覚え書きなどを書くスペースがほしかったので、ブログを始めてみました。