| 著作一覧 |
ActiveScriptエンジンにJScriptを選択した場合の一番の問題はin/outパラメータにある。
in/outパラメータというのは、具体的には、引数に対して値を返せるものだ。Cならお馴染みなので、Javaでもやりたがる人がいて、無理矢理配列にしたりするあれである。
void c_func(int* p) {
*p = result_value;
}
を無理にJavaでやろうとして
void java_method(int[] p) {
p[0] = result_value;
}
で、ActiveScriptは本来的にVBScriptがプライマリ言語なので、当然のように呼び出し可能なCOMコンポーネントにも山ほどin/outパラメータが出てくる。
interface COMobject {
[id(1)] HRESULT hello([in,out]BSTR* greeting, [out, retval]long* pResult);
}
でVBScriptだと
dim greeting If object.hello(greeting) = 0 Then WSH.echo greeting '結果が返っている End Ifで、このてのやつをJScriptから呼ぼうとすると型エラーとなる。
var greeting;
if (object.hello(greeting) == 0) { // エラー型違い
WSH.echo(greeting);
}
と言う問題があって、JavaScriptを使いたくてもVBScriptを選択せざるを得ないことがあった。
HRESULT Wrapper::Invoke(....) {
IDispatchEx* p; // JScriptのオブジェクトはIDispatchExなので話が簡単
pDispParams->rgvargs[0].pdispVal->QueryInterface(IID_IDispatchEx, (void**)&p);
DISPID dispid;
p->GetDispID(CComBSTR(L"value"), 0, &dispid);
VARIANT var;
p->InvokeEx(dispid, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &noargs, &var, 0, 0);
p->Release();
pDispParams->rgvargs[0].vt = VT_BSTR | VT_BYREF; // idlのin,outの型に合わせる。
pDispParams->rgvargs[0].pbstrVal = &var.bstrVal;
HRESULT hr = wrappedInterface->Invoke(....);
return hr;
}
呼び出し側は上に合わせて
var inoutparam = { value: '' };
if (objectWrapper.hello(inoutparam) == 0) {
WSH.echo(inoutparam.value);
}
もっともJavaScript同士と同様に、値オブジェクトの利用が正解だとは思う。
function hello() {
return { greeting: 'hello world', // Javaでもこのくらい簡単に記述できれば配列をパラメータにして結果を返すなどという妙なことをする人は出て来なかっただろうな。
resultCode: 0
};
}
と同じように、
interface Result {
[id(1), propget] HRESULT greeting([out, retval]BSTR* p);
[id(2), propget] HRESULT result([out, retval]long* p);
}
で、
var r = object.hello();
if (r.result == 0) { // なぜ戻りコードが必要かは謎。エラーなら例外で良いのではなかろうか。
WSH.echo(r.greeting);
}
ジェズイットを見習え |