Search code examples
javascriptc++com

Return multiple variables to JavaScript from COM


I have COM function in a disp interface as shown below,

[id(1)] HRESULT MultipleReturn([out]BSTR* arg1, [out, retval] BSTR* arg2);

implemented as

STDMETHODIMP SomeCoolObject::MultipleReturn(BSTR* arg1, BSTR* arg2)
{
    *arg1 = SysAllocString(L"test1");
    *arg2 = SysAllocString(L"test2");
    return S_OK;
}

In Python I can call it as

import comtypes.client as cc

obj = cc.CreateObject('SomeCoolObject')
a = obj.MultipleReturn()
print(a) # gives (u'test1', u'test2'), Python, I see you don't bite :)

same in JavaScript

var obj = new ActiveXObject("SomeCoolObject")

// this gives error, kind of obvious
// 'Wrong number of arguments or invalid property assignment'
// var val = obj.MultipleReturn();

var a = "holaaa!";
var val = obj.MultipleReturn(a);
alert(val); // gives "test2"
alert(a);   // gives "holaaa!", may be could have given "test1"

this proves, JavaScript won't play this ball. Why? If not, then how do you return multiple values from COM to JavaScript. For this particular job, I returned a JSON though.


Solution

  • JavaScript/COM binding doesn't support [out] parameters - only [out, retval] (of which, of course, there can only be one). JavaScript generally doesn't have a notion of pass-by-reference.

    There are several ways you can get closer to your goal.

    1. Return a SAFEARRAY of two strings. In JavaScript, consume it via VBArray object.

    2. Implement a simple COM object with two BSTR properties, create and return an instance of that object via [out, retval] IDispatch**.

    3. Take IDispatch* as an [in] parameter, set a new property on it via IDispatchEx::GetDispID(fdexNameEnsure). JavaScript would consume it like this:

    .

    var outParam = {};
    var result = obj.MultipleReturn(outParam);
    var secondResult = outParam.value;
    

    (where value is the name of the property your method creates on the object).