ActiveX Double return value passed by reference?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

ActiveX Double return value passed by reference?

Christopher J. Demers
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 just
need to do it the right way.  Does anyone know the right way?

This is the Smalltalk method definition:
==========================
getDouble: fIx pdVal: pdVal
 "Answer the <VARIANT_BOOL> result of invoking the COM Object's GetDouble()
method."

 ^(self invokeId: 9 with: fIx with: pdVal)

This is the C++ declaration:
====================
afx_msg BOOL GetDouble(short fIx, double FAR* pdVal);

Any ideas would be much appreciated, thanks.

Chris


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX Double return value passed by reference?

Blair McGlashan
Christopher

You wrote in message news:92th8r$8gg8d$[hidden email]...

> 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
just
> 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
GetDouble()
> method."
>
>  ^(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):

doubleAt: anInteger
| answer |
answer := VARIANT new
                vt: (VT_R8|VT_BYREF);
                reference: DOUBLE new;
                yourself.
^(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.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX Double return value passed by reference?

Christopher J. Demers
Blair McGlashan <[hidden email]> wrote in message
news:92v26o$87rjv$[hidden email]...
> 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

Yes, I believe that is the case.  This component is a bit of a "me to"
affair.  The provider started with C++ classes, and just slapped on an
ActiveX wrapper to make it easy to use in VB I guess.  The interface they
provided seems fairly primitive for an ActiveX component.

> 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):

I figured this should have been easier to do, at least I was on the right
track.

>
> doubleAt: anInteger
> | answer |
> answer := VARIANT new
>                 vt: (VT_R8|VT_BYREF);
>                 reference: DOUBLE new;
>                 yourself.
> ^(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.

Much thanks Blair, this does exactly what I need! :)

Chris