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 |
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 > 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 |
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 > 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 |
Free forum by Nabble | Edit this page |