Returning a SafeArray of VARIANT BSTRs The following code demonstrates how to return the SafeArray of VARIANTs of type VT_BSTR constructed in the preceding section "Constructing A SafeArray Using SafeArrayPutElements", The following code takes a long as an input parameter and creates a SafeArray of VARIANTS of the corresponding length. The IDL looks like this:[id(1), helpstring("method GetArray")] HRESULT GetArray([in] int newVal, [out, retval] VARIANT *pVal);It is important to note the the out VARIANT *pVal is not initialized on entry to the method. If you call a method such as CComVariant.Detach(pVal), the out VARIANT will be cleared. Since the out VARIANT is not yet initialized, it contains random data. Clearing a VARIANT of random data is not recommended! The following code sample also calls the MACROS V_VT and V_ARRAY. These are poorly documented, but available for review in the header file oleauto.h. Again, I modeled the C++ and ASP code after Shelley Powers "Developing ASP Components Second Edition". // ASSERT newVal > 0 STDMETHODIMP CArray::GetArray(int newVal, VARIANT *pVal) { // TODO: Add your implementation code here USES_CONVERSION; char buffer[20]; HRESULT hr= S_OK; if (newVal < 1) { newVal= 1; } // Create SafeArray of VARIANT BSTRs SAFEARRAY *pSA; SAFEARRAYBOUND aDim[1]; aDim[0].lLbound= 0; aDim[0].cElements= newVal; pSA= SafeArrayCreate(VT_VARIANT,1,aDim); if (pSA != NULL) { _variant_t vOut; for (long l= aDim[0].lLbound; l< (aDim[0].cElements + aDim[0].lLbound); l++) { ltoa(l,buffer,10); vOut= A2W(buffer); if (hr= SafeArrayPutElement(pSA, &l, &vOut)) { SafeArrayDestroy(pSA); // does a deep destroy return hr; } } }// return SafeArray as VARIANT //VariantInit(pVal); // WARNING You must initialize *pVal before calling Detach V_VT(pVal)= VT_ARRAY | VT_VARIANT; //pVal->vt= VT_ARRAY | VT_VARIANT; // oleauto.h V_ARRAY(pVal)= pSA; // (pSA may be null) //pVal->parray= pSA; // oleauto.h return S_OK; } You can call the code from VBScript like this:<%@ LANGUAGE="VBScript" %> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" content="text/html; charset=iso-8859-1"> <TITLE>Test Array DLL</TITLE> </HEAD> <BODY TopMargin="0" Leftmargin="0"> <% Set objArray= Server.CreateObject("JALArray.Array") Dim arrayBSTR Dim x arrayBSTR= objArray.GetArray(10) for x= LBound(arrayBSTR) to UBound(arrayBSTR) Response.write "<BR>"&x&": "&arrayBSTR(x) next Set objArray= nothing %> </BODY> </HTML>Calling the code from JScript is more complicated:<%@ LANGUAGE="JSCRIPT" %> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" content="text/html; charset=iso-8859-1"> <TITLE>Test Array DLL</TITLE> </HEAD> <BODY TopMargin="0" Leftmargin="0"> <% var objArray= Server.CreateObject("JALArray.Array") ; var arrayVariants= new VBArray(objArray.GetArray(10)); var arrayBSTR= arrayVariants.toArray(); for (i= arrayVariants.lbound();i<= arrayVariants.ubound(); i++) { Response.write("<BR>"+i+": "+arrayBSTR[i]+""); } objArray= null; %> </BODY> </HTML>
The following code demonstrates how to return the SafeArray of VARIANTs of type VT_BSTR constructed in the preceding section "Constructing A SafeArray Using SafeArrayPutElements", The following code takes a long as an input parameter and creates a SafeArray of VARIANTS of the corresponding length. The IDL looks like this:[id(1), helpstring("method GetArray")] HRESULT GetArray([in] int newVal, [out, retval] VARIANT *pVal);It is important to note the the out VARIANT *pVal is not initialized on entry to the method. If you call a method such as CComVariant.Detach(pVal), the out VARIANT will be cleared. Since the out VARIANT is not yet initialized, it contains random data. Clearing a VARIANT of random data is not recommended! The following code sample also calls the MACROS V_VT and V_ARRAY. These are poorly documented, but available for review in the header file oleauto.h. Again, I modeled the C++ and ASP code after Shelley Powers "Developing ASP Components Second Edition".
// ASSERT newVal > 0
STDMETHODIMP CArray::GetArray(int newVal, VARIANT *pVal)
{
// TODO: Add your implementation code here
USES_CONVERSION;
char buffer[20];
HRESULT hr= S_OK;
if (newVal < 1) {
newVal= 1;
} // Create SafeArray of VARIANT BSTRs
SAFEARRAY *pSA;
SAFEARRAYBOUND aDim[1];
aDim[0].lLbound= 0;
aDim[0].cElements= newVal;
pSA= SafeArrayCreate(VT_VARIANT,1,aDim);
if (pSA != NULL) {
_variant_t vOut;
for (long l= aDim[0].lLbound; l< (aDim[0].cElements + aDim[0].lLbound); l++) {
ltoa(l,buffer,10);
vOut= A2W(buffer);
if (hr= SafeArrayPutElement(pSA, &l, &vOut)) {
SafeArrayDestroy(pSA); // does a deep destroy
return hr;
}
}
}// return SafeArray as VARIANT
//VariantInit(pVal); // WARNING You must initialize *pVal before calling Detach
V_VT(pVal)= VT_ARRAY | VT_VARIANT; //pVal->vt= VT_ARRAY | VT_VARIANT; // oleauto.h
V_ARRAY(pVal)= pSA; // (pSA may be null) //pVal->parray= pSA; // oleauto.h
return S_OK;
}
You can call the code from VBScript like this:<%@ LANGUAGE="VBScript" %>
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" content="text/html; charset=iso-8859-1">
<TITLE>Test Array DLL</TITLE>
</HEAD>
<BODY TopMargin="0" Leftmargin="0">
<%
Set objArray= Server.CreateObject("JALArray.Array")
Dim arrayBSTR
Dim x
arrayBSTR= objArray.GetArray(10)
for x= LBound(arrayBSTR) to UBound(arrayBSTR)
Response.write "<BR>"&x&": "&arrayBSTR(x)
next
Set objArray= nothing
%>
</BODY>
</HTML>Calling the code from JScript is more complicated:<%@ LANGUAGE="JSCRIPT" %>
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" content="text/html; charset=iso-8859-1">
<TITLE>Test Array DLL</TITLE>
</HEAD>
<BODY TopMargin="0" Leftmargin="0">
<%
var objArray= Server.CreateObject("JALArray.Array") ;
var arrayVariants= new VBArray(objArray.GetArray(10));
var arrayBSTR= arrayVariants.toArray();
for (i= arrayVariants.lbound();i<= arrayVariants.ubound(); i++) {
Response.write("<BR>"+i+": "+arrayBSTR[i]+"");
}
objArray= null;
%>
</BODY>
</HTML>
谢谢