JScript配列をCOM(C++)で参照する

ちょっとした経緯で,JScriptから呼び出されるCOMをC++で実装することになりました。

そこでJScriptからCOMに対して,パラメータとして配列を渡す必要があったのですが,JScriptで扱う配列は,COMで通常扱うSafeArray配列ではないということをことを知りました。Webでいろいろ調べてみると,"length"と配列インデックス("0","1","2",...)をメソッドとして持つIDispatchインターフェースとして渡されているようです。

このインターフェース(JScript配列)を,COM内部で取り扱う形式に変換する処理を作成してみましたので,紹介します。なお,今回扱っているのは旧版のJScriptで,.Net 言語になった新しいもの(JScript.Net)には当てはまりませんので,その点了承下さい。

最初にIDispatchインターフェースを介して"name"で指定したプロパティ値を取得するメソッドを用意します。

CComVariant JsArray::GetIDispatchProperty(IDispatch* iDisp,
const char* name) {
HRESULT hr;

DISPID dispid = 0;
OLECHAR FAR* szMember = CA2W(name);
hr = iDisp->GetIDsOfNames(IID_NULL, &szMember, 1,
LOCALE_SYSTEM_DEFAULT, &dispid);
if(FAILED(hr)) {
throw exception("IDispatch::GetIDsOfNames");
}

DISPPARAMS params = { NULL, NULL, 0, 0 };
VARIANT var;
EXCEPINFO excepinfo;
UINT nArgErr;
hr = iDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, ¶ms, &var,
&excepinfo, &nArgErr);
if(FAILED(hr)) {
throw exception("IDispatch::Invoke");
}

return CComVariant(var);
}
このメソッドを使って,JScript配列の要素数を取得します。
要素数は,プロパティ"length"から取り出せる整数値(VT_I4)です。

int JsArray::GetJScriptArrayLength(IDispatch* iDispatch) {
CComVariant length = GetIDispatchProperty(iDispatch, "length");
HRESULT hr = length.ChangeType(VT_I4);
if(FAILED(hr)) {
throw exception("CComVariant::ChangeType(VT_I4)");
}
return length.intVal;
}
要素数を参照して,配列の内容を取得するメソッドを作成します。

配列値はVariantで格納されているので,CComVariant配列(Vector)として取得しています。

vector JsArray::GetJScriptArrayValues(IDispatch* iDispatch) {
int length = GetJScriptArrayLength(iDispatch);
std::vector result(length);
for(int n = 0; n < length; ++n) {
char str[10];
::sprintf(str, "%d", n);
result[n] = GetIDispatchProperty(iDispatch, str);
}
return result;
}
後は取得したVariant配列の各要素を,所定の型の値として参照すればOKです。


タグ:C++ com
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック
rank← ランキングはこちらをクリック!

×

この広告は180日以上新しい記事の投稿がないブログに表示されております。