Firefox ExtensionでC++プログラムを動かしてみるテスト 〜その6 文字列を扱ってみる〜
かーねる・う゛いえむにっきからの続き。
前回までに作ったExtentionはキー・バリューをlongにしていたので文字列が扱えなかった。また、一定以上の数値をkeyに渡すことが出来なかった。これではカッコ悪い。
という訳で、前回までに実装したXPCOMモジュールに手を加えて文字列を扱えるようにし、storeは配列ではなくC++のstd::mapを使ったハッシュテーブルにしてみる。
testIKVS.idl
#include "nsISupports.idl" [scriptable, uuid(3A5769F0-8F50-465A-8682-4C0F0F76AE4F)] interface testIKVS : nsISupports { void open(); string get(in string key); void put(in string key, in string value); void close(); };
longだった所をstringにする。これはxpidlに渡すとchar *になる:
testIKVS.h
class NS_NO_VTABLE NS_SCRIPTABLE testIKVS : public nsISupports { public: NS_DECLARE_STATIC_IID_ACCESSOR(TESTIKVS_IID) /* void open (); */ NS_SCRIPTABLE NS_IMETHOD Open(void) = 0; /* string get (in string key); */ NS_SCRIPTABLE NS_IMETHOD Get(const char *key, char **_retval NS_OUTPARAM) = 0; /* void put (in string key, in string value); */ NS_SCRIPTABLE NS_IMETHOD Put(const char *key, const char *value) = 0; /* void close (); */ NS_SCRIPTABLE NS_IMETHOD Close(void) = 0; };
さて、実装してみよう。
testKVS.h
#ifndef __TESTKVS_H__ #define __TESTKVS_H__ #include <map> #include <string> #include "testIKVS.h" class testKVSImpl : public testIKVS { public: NS_DECL_ISUPPORTS NS_DECL_TESTIKVS testKVSImpl(); private: ~testKVSImpl(); std::map<std::string, std::string> store; }; #endif
storeをmapにし、プライベートメンバ変数として定義。
testKVS.cpp
#include "testKVS.h" NS_IMPL_ISUPPORTS1(testKVSImpl, testIKVS) testKVSImpl::testKVSImpl() { } testKVSImpl::~testKVSImpl() { } /* void open (); */ NS_IMETHODIMP testKVSImpl::Open() { return NS_OK; } /* long get (in long key); */ NS_IMETHODIMP testKVSImpl::Get(const char *key, char **_retval NS_OUTPARAM) { std::string _key(key), _val = store[_key]; char *retval = (char *)calloc(_val.length(), sizeof(char)); strncpy(retval, _val.c_str(), _val.length()); *_retval = retval; return NS_OK; } /* void put (in long key, in long value); */ NS_IMETHODIMP testKVSImpl::Put(const char *key, const char *val) { std::string _key(key), _val(val); store[_key] = _val; return NS_OK; } /* void close (); */ NS_IMETHODIMP testKVSImpl::Close() { return NS_OK; } /* End of implementation class template. */
変える事になるのはGet()とPut()。
入出力はchar *だがstoreへはstd::stringで記録するので、毎度インスタンスを生成する。
Get()でわざわざアロケート・コピーしているのは、どうやら_retvalはブラウザ側でfree()したいらしいから。
# _val.c_str()を直接returnするとfirefoxのデバッグモードでエラーが出る。
出来上がったらビルドしてextentionにコピー。
$ make DEPTH=~/191src topsrcdir=~/191src $ cp ./_xpidlgen/testIKVS.xpt ~/Library/Application\ Support/Firefox/Profiles/*/extensions/testkvs\@dokukino.com/components/ $ cp libtestkvs.dylib ~/Library/Application\ Support/Firefox/Profiles/*/extensions/testkvs\@dokukino.com/platform/Darwin_x86-gcc3/components
Firefoxを起動して、get, putしてみる。
文字列でもきちんとget, putできている。
が、しかし、日本語が扱えない。
実は、これを扱うにはMozilla内部のワイドキャラクタ対応文字列クラスを使う必要がある。
この話はまた今度。