[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 734
  • Last Modified:

How to pass a Safe Array to an Automation server?

I added an Automation object to the application I am working on.  This allows our clients using Visual Basic to access our application's functionality easily.  Everything works fine except when I want to pass arrays of data between a Visual Basic application and my MFC application.  The type of the Variant is VT_ARRAY as expected but the dimension and the element size are random values.

I added a method to my CCmdTarget-derived class using Class Wizard.  This gives...

BOOL CApplication::GetDoubleArray(const VARIANT FAR& varArray)
{
// Make sure the input value in an array
VARTYPE vType=V_VT(&varArray);
ASSERT(vType & VT_ARRAY);
if (vType & VT_ARRAY)
{
   // Things do not work as expected starting from here...

   // lDim and lElemSize are never OK (They seem to be random.)
   long lDim=SafeArrayGetDim(V_ARRAY(&varArray));
   long lElemSize=SafeArrayGetElemsize(V_ARRAY(&varArray));

   // Show that lDim and lElemSize are random values
   CString strMsg;
   strMsg.Format("lDim=%d  lElemSize=%d", lDim, lElemSize);
   AfxMessageBox(strMsg);
}

return TRUE;
}

and...

[id(3)] boolean GetDoubleArray(VARIANT varArray);

in the ODL file.

On Visual Basic side, the code is...

Dim MyObj As Object
Set MyObj = CreateObject("MyObj.Application")
Dim dArray() As Long
ReDim dArray(0 To 10)
MyObj.GetDoubleArray dArray


I have the same problem with in-process and out-of-process Automation servers.
If I add the same method in an ActiveX Control, everything works fine!

Any help will be appreciated.

0
blarivie
Asked:
blarivie
  • 2
1 Solution
 
Tommy HuiEngineerCommented:
My guess is that you should check the type of the array to see if it has VT_BYREF. I'm betting the type is different in the two cases.
0
 
blarivieAuthor Commented:
You are right, I have VT_BYREF in the Automation server and not in the ActiveX Control.
Now, what should I do to make it work in my Automation server?
0
 
blarivieAuthor Commented:
Finally, your answer led me to a solution: use "VARIANT FAR*" instead of "const VARIANT FAR&"...  (The other solution is to use the pparray field of the input const VARIANT FAR&. - not discussed here)

BOOL CApplication::GetDoubleArrayPointer(VARIANT FAR* pvarArray)
{
   ASSERT(pvarArray!=NULL);
   if (pvarArray!=NULL)
   {
      VARTYPE vType=V_VT(pvarArray);

      ASSERT((vType&VT_ARRAY) && (vType&VT_R8));
      if ((vType&VT_ARRAY) && (vType&VT_R8))
      {
         SAFEARRAY FAR* psa=V_ARRAY(pvarArray);

         long lDim=SafeArrayGetDim(psa);
         long lElemSize=SafeArrayGetElemsize(psa);

         ASSERT((lDim==1) && (lElemSize==sizeof(double)));
         if ((lDim==1) && (lElemSize==sizeof(double)))
         {
            long lUpper, lLower;
            SafeArrayGetLBound(psa, 1, &lLower);
            SafeArrayGetUBound(psa, 1, &lUpper);
            long lNumItems=lUpper - lLower + 1;

            HRESULT hres;
            if (hres=SafeArrayLock(psa))
               throw hres;

            for (long lIndex=0; lIndex<lNumItems; lIndex++)
            {
               // Testing: return square of index
               ((double*)psa->pvData)[lIndex]=(double)lIndex*lIndex;
            }

            if (hres=SafeArrayUnlock(psa))
               throw hres;
         }
      }
   }

   return TRUE;
}

In Dispatch Map:
DISP_FUNCTION(CApplication, "GetDoubleArrayPointer", GetDoubleArrayPointer, VT_BOOL, VTS_PVARIANT)

In ODL file:
[id(3)] boolean GetDoubleArrayPointer(VARIANT* pvarArray);

In Visual Basic:
Dim MyObj As Object
Set MyObj=CreateObject("MyApp.Application")
Dim v As Variant
ReDim v(0 To 10) As Double
Script.GetDoubleArrayPointer(v)
For i=0 To 10
   MsgBox Str(v(i)), vbOkOnly, "GetDoubleArrayPointer()"
Next i

I found this solution in a Microsoft Knowledge Base Article: "HOWTO: Pass a SafeArray of Strings in a VARIANT*" (Q167668)

0

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now