ActiveX Double return value passed by reference?
> I am trying to use an ActiveX control in Dolphin 4.0. It is non-GUI, but
> needs to be in an AXControlSite. I have also generated the Smalltalk
> classes for the ActiveX classes I am using. It works OK, except for some
> situations where I need to get a return value that is passed by reference.
> I can get values passed by reference from standard DLL's by using
> ExternalAddress, that works fine. However that does not seem to work for
> ActiveX. I have tried variations, passing a DOUBLE object, and just about
> anything else I could think of. Nothing works and I get this error:
> 'HRESULT Error: Type mismatch. (FACILITY_DISPATCH)'. I could not find any
> documentation about this. I assume that this can be done in Dolphin, I
> need to do it the right way. Does anyone know the right way?
Generally speaking the Active-X wizard will create a correctly defined
"high-level" wrapper method that wraps output arguments appropriately.
However it has to rely on the type information in the type library to do
this, so if parameters are not marked with the "out" attribute, then it
can't do that. So the first problem would appear to be that the real return
value is not so marked - certainly it seems that the wizard hasn't
recognised the second parameter as an output.
> This is the Smalltalk method definition:
> getDouble: fIx pdVal: pdVal
> "Answer the <VARIANT_BOOL> result of invoking the COM Object's
> ^(self invokeId: 9 with: fIx with: pdVal)
It seems as if there is only a dispinterface? The wizard only generates
those sort of wrappers in that case (otherwise it calls directly through the
vtbl). Anyway if it is a dispinterface, then all the arguments need to get
wrapped as VARIANTs. #invokeId:etc does do that, but is relies on the
#asVariant conversions of the arguments you pass it. DOUBLE implements
#asVariant to create a VT_R8, which will not work as an output argument.
So the second problem is that DOUBLE>>asVariant is not correctly defined; it
should be following the pattern of its superclass, ExternalStructure, which
creates a reference (VT_BYREF) style variant which points at its content,
i.e. DOUBLE>>asVariant should really create a VT_R8|VT_BYREF, the correct
implementation being similar to ExternalInteger>>asVariant. We'll fix that
in PL2, but in the meantime you should be able to invoke it as follows (I'd
suggest you add the a method to the interface):
| answer |
answer := VARIANT new
reference: DOUBLE new;
^(self getDouble: anInteger-1 pdVal: ref)
ifTrue: [answer value]
This will answer nil if the method returns false (I assume the boolean
return value is a success/failure indication?), although you might prefer to
raise an exception depending on what the bool return value actually means.
You'll notice I've deducted one from the argument, on the assumption that
fIx is an index, and that fIx should be zero based, whereas Smalltalk
conventionally uses one-based indices.