Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passing strings and arrays to/from scripting languages

0 views
Skip to first unread message

Noël Danjou

unread,
Dec 8, 2004, 6:09:19 AM12/8/04
to
Visual Studio .NET 2003
Windows XP Professional SP2

Hello,

I am trying to write an ATL DLL that implements a simple ATL object that
exposes a few methods to be called from JSCript, VBScript, VB and C++.

I only succeed in reading a string (BSTR) from the scripting language in my
DLL but I cannot read an array of BSTR or to return a BSTR or an array of
BSTR.

Here is an example of what I'd like to achieve:

sample.htm------------

<script language="jscript">
var obj = new ActiveXObject("MyObject.IMyInterface.1");

var message = "<msg>";
if (obj.GetString("Noel", message))
{
// This fails
alert(message);
}

var arIn = new Array(2);
arIn[0] = "first";
arIn[1] = "second";

var arOut = new Array();

if (obj.GetArray(arIn, arOut))
{
// This fails
alert(arOut[0]);
}
</script>

------------------------

Here is an example of my code:

sample.cpp------------

__interface IIMyInterface : IDispatch

{

...

[id(1), helpstring("method GetString")] HRESULT GetString([in] BSTR
bstrType, [out] BSTR* pbstrSyntax, [out,retval] VARIANT_BOOL* pbReturn);

[id(2), helpstring("method GetArray")] HRESULT GetArray([in] VARIANT*
pInArray, [out] VARIANT* pOutArray, [out,retval] VARIANT_BOOL* pbReturn);

...

}

...

public:

STDMETHOD(GetString)(BSTR bstrName, BSTR* pbstrMessage, VARIANT_BOOL*
pbReturn);

STDMETHOD(GetArray)(VARIANT* pInArray, VARIANT* pOutArray VARIANT_BOOL*
pbReturn);

...

STDMETHODIMP CIMyInterface::GetString(BSTR bstrName, BSTR* pbstrMessage,
VARIANT_BOOL* pbReturn)

{

if (bstrName == NULL || pbstrMessage == NULL || pbReturn == NULL)

{

return E_POINTER;

}

else

{

CString strName(bstrName);

CString strMessage = _T("Hello ");

strMessage += strName;


*pbstrMessage = strMessage.AllocSysString();

*pbReturn = VARIANT_TRUE;

return S_OK;

}

}

STDMETHODIMP CIMyInterface::GetArray(VARIANT* pInArray, VARIANT* pOutArray,
VARIANT_BOOL* pbReturn)

{

if (pInArray == NULL || pOutArray == NULL || pbReturn == NULL)

{

return E_POINTER;

}

else

{

SAFEARRAY *psa;

if (V_VT(pInArray) & VT_BYREF)

psa = *V_ARRAYREF(pInArray);

else

psa = V_ARRAY(pInArray);

// Fails, data pointed by psa are meaningless

CComSafeArray<BSTR> saSrc(psa);

...

CComSafeArray<BSTR> saOut;

CString strOut = _T("TestOut");

saOut.Add(strOut.AllocSysString());

VariantInit(pOutArray);

V_VT(pOutArray) = VT_ARRAY | VT_VARIANT;

V_ARRAY(pOutArray)= saOut.Detach();


*pbReturn = VARIANT_TRUE;

return S_OK;

}

}

---------------

For arrays I also tried to use a syntax like below to no avail:

[id(2), helpstring("method GetArray")] HRESULT GetArray([in, satype("BSTR")]
SAFEARRAY** pInArray, [out, satype("BSTR")] SAFEARRAY** pOutArray,
[out,retval] VARIANT_BOOL* pbReturn);

Could you please tell me what I am doing wrong and how to fix it. Thank you.

--
Noël

Igor Tandetnik

unread,
Dec 8, 2004, 11:16:19 AM12/8/04
to
"Noël Danjou" <no...@online.nospam> wrote in message
news:%23k28paR...@TK2MSFTNGP11.phx.gbl

> I only succeed in reading a string (BSTR) from the scripting language
> in my DLL but I cannot read an array of BSTR or to return a BSTR or
> an array of BSTR.

VBScript can read and produce safearrays of variants, but not of any
other type. JavaScript can read safearrays of any type with the help of
VBArray object, but cannot produce any kind of safearray. An Array
object in JavaScript is not in any way related to a safearray - it's an
object implementing IDispatch, with each index being a separate
property. VBArray can convert a safearray to a JavaScript Array, but
there's no conversion the other way.

A preferred way to pass a set of items to scripts is to create a
collection object.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Noël Danjou

unread,
Dec 9, 2004, 9:46:49 AM12/9/04
to
Hello Igor,

Thanks for your information and suggestion. I will implement a collection
object.

By the way are there any native BSTR collection objects available in
Windows? This should be a quite common task.

Is the problem the same with "[out] BSTR*" ? Should I use collection object
to just return a string in a parameter?

Thank you.
--
Noël


Igor Tandetnik

unread,
Dec 9, 2004, 10:35:54 AM12/9/04
to
"Noël Danjou" <no...@online.nospam> wrote in message
news:uaAyu3f3...@TK2MSFTNGP14.phx.gbl

> By the way are there any native BSTR collection objects available in
> Windows? This should be a quite common task.

None that I know of. But ATL has a decent support for collection
objects - see ATLCollections sample.

> Is the problem the same with "[out] BSTR*" ? Should I use collection
> object to just return a string in a parameter?

Again, JavaScript does not support pass by reference. So if you have an
[out] parameter, this won't work in JavaScript (but a VBScript
equivalent works):

var str = "";
myObj.SomeMethod(str); // expect the method to change the string

Change the parameter to [out, retval], then this will work in both
JavaScript and VBScript:

var str = myObj.SomeMethod();

So, BSTR itself is not a problem. [out] parameters of any kind other
than [out, retval] are a problem (for any type, not just BSTR), and
safearrays (again, of any type, not just BSTR) are another problem.

Noël Danjou

unread,
Dec 10, 2004, 11:20:57 AM12/10/04
to
Thanks again for all your information. I can now handle arrays successfully.

I also use the VBArray object to convert the returned safearrays of BSTR to
JS arrays.

Sincerely,
--
Noël


0 new messages