Parameter Passing Between VB and VC++’s ActiveX DLL

In one of the tasks of my project, I have to create an ActiveX DLL using VC++ MFC Framework to provide some data to VB application. More specifically, one of the methods inside the ActiveX DLL should returned an array of VB’ s double type.

At first, I try using some rudimentary samples I got from either the MSDN documentation using the SAFEARRAY data type. After I already performing some necessary coding requirements, to test the sanity of the passed parameter from VB, I just returned one of the acquired properties of the supposed SAFEARRAY data type, such as the dimension :

long myDataCtrl::myArrayTest(SAFEARRAY *saTest)
return saTest->cDims;

And inside the VB test application on the click event, I just created some small codings just to show the returned value :

Dim aVar() As Double
Dim nResult As Long
Dim oTest As Object
Set oTest = CreateObject(“myControl.1”)
nResult = oTest.myArrayTest(aVar)
MsgBox nResult

If everything is according to scenario, the returned value should be of valid dimension such as 1. But in this case, the returned value is 24581 or hex 0x6005. This value is actually a variant type enumeration that consists of VT_BYREF | VT_ARRAY | VT_R8, which reads “parameter passed by reference, that’s consists of array of variable of double numeric type”.

Certainly this is not a SAFEARRAY type as expected. I think because at my current development environment the DISP_FUNCTION_ID dispatch mapping do not supports the array type for their argument list.

So, that leaves me only the VARIANT type as the only choice for parameter passing. So, again, I perform some parameter type change to the variant type :

long myDataCtrl::myArrayTest(VARIANT *saTest)
return saTest->vt;

And indeed, the returned value is still 0x6005. I can now continue to access the passed safe array from VB by resizing the dimension and assigned the necessary values to the caller (i.e. VB application). But first, let’s test it whether this conjecture is true, by checking the passed dimension information :

pMySafeArray = saTest->parray;
return pMySafeArray->cDims;

It returns the zero, since I haven’t decide the dimension yet in the VB declaration for the variable, because it will be decided inside the called method. So far so good, now the next step is try to resize the array dimension :

hr = SafeArrayAllocDescriptor(1, &saTest->parray);
return saTest->parray->cDims;

This time, Inside called method (ActiveX DLL) the dimension can be changed, but it is not reflected in the VB application. Scratching my head, I think this is because I haven’t yet revise the argument type list inside DISP_FUNCTION_ID from VTS_VARIANT which is passed by value, to VTS_PVARIANT, to be passed by reference.

But by changing it to VTS_PVARIANT causes the VB application breaks down by showing the “Type Mismatch” error.

What happened here ? Well, I supposed because at the time when VTS_PVARIANT is declared, the ActiveX DLL tries to return the VARIANT type, whereas VB application expects an array type of the data, hence the “Type Mismatch” error.

So, I have a deadlock situation here, the parameter can be passed in, but it is trapped, can’t go out. In order to resolve this situation, how about I just declared the Variant type in VB application :

Dim aVar As Variant

And, leaving the VTS_PVARIANT, I activates the application, calls the method, which just returned the variable type. I am happy because this time it works !

Next, I perform the re-run of the above procedure, and this time, the modifications inside the method is now reflected in the calling VB application đŸ™‚


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: