I have created a COM server which works properly when I use
srv:=IDispatch createObject: 'Myserver.server'. srv invoke: 'func' with: param. However I feel this may be slowing it down for certain functions and I tried using the Active X wizard. I am not sure if I am doing this right,. After the wizard generates the MyserverIserver class under IDispatch I am not sure which is the best way to go about intantiating it and invoking functions. I did the following but I have problems: srv:=MyserverIserver on: 'Myserver.server'. srv invoke: 'func' with: param. On the #invoke line I get a does not understand message: GetIDsOfNames:rgszNames:cNames:lcid:rgdispid: arguments: #(a REFGUID{00000000-0000-0000-0000-000000000000} a LPVOID(an ExternalAddress(16r8226754)) 1 1024 a SDWORD(0)) Ami I instantiating this correctly? ShouldI be using invoke? What am I missing? Thanks Costas Menico |
Costas,
I think you still want to use #createObject: to get your IDispatch subinstance. The benefit of the ActiveX Wizard will be to use the generated methods as opposed to #invoke:with:. Your code would look more like srv:=IDispatch createObject: 'Myserver.server'. srv func:param. Does that help? Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
"Bill Schwab" <[hidden email]> wrote:
>Costas, > >I think you still want to use #createObject: to get your IDispatch >subinstance. The benefit of the ActiveX Wizard will be to use the generated >methods as opposed to #invoke:with:. Your code would look more like > > srv:=IDispatch createObject: 'Myserver.server'. > srv func:param. > >Does that help? You bet it helps! Thanks so much Costas |
In reply to this post by Costas Menico-2
Costas
"Costas Menico" <[hidden email]> wrote in message news:[hidden email]... > I have created a COM server which works properly when I use > > srv:=IDispatch createObject: 'Myserver.server'. > srv invoke: 'func' with: param. > > However I feel this may be slowing it down for certain functions and I > tried using the Active X wizard. I'm not sure if I am doing this right,. After the wizard generates > the MyserverIserver class under IDispatch I am not sure which is the > best way to go about intantiating it and invoking functions. Going through IDispatch will indeed be significantly slower (probably two orders of magnitude) than invocation through a generated interface. Once generated you can treat it as a normal Smalltalk object since the wizard generated "high-level" wrapper methods that hide most of the argument/return value marshalling. Take a look at the generated class - it also includes a lot of "documentation", generated from the type library, which makes it much easier to discover how use an Active-X component by expirementation. > I did the following but I have problems: > > srv:=MyserverIserver on: 'Myserver.server'. > srv invoke: 'func' with: param. > If the interface is defined as the default for the Active-X component, then you can probably just do: srv := MyserverIserver new. Try it anyway, you'll get a "#clsid is the responsibility of the subclass" error if not, in which case: srv := MyserverIserver createObject: 'Myserver.server' will work. You can then invoke the methods and property accessors as normal Smalltalk message sends, e.g. srv func. You can also add further "helper" methods to the interface class which make it easier to use, or whatever. Regards Blair |
"Blair McGlashan" <[hidden email]> wrote:
>> >> srv:=MyserverIserver on: 'Myserver.server'. >> srv invoke: 'func' with: param. >> > >If the interface is defined as the default for the Active-X component, then >you can probably just do: > > srv := MyserverIserver new. > >Try it anyway, you'll get a "#clsid is the responsibility of the subclass" >error if not, in which case: > > srv := MyserverIserver createObject: 'Myserver.server' > >will work. You can then invoke the methods and property accessors as normal >Smalltalk message sends, e.g. > > srv func. > Blair, Just wanted to report back to you what works and what doesn't work and see if there is anything else I should check or test. Assume the method to invoke is func: param This always works: =============== srv := IDispatch createObject: 'Myserver.server'. srv invoke: 'func' with param. This partially works =============== srv := IDispatch createObject: 'Myserver.server'. srv func: param. The func executes correctly but always returns nil. I get the answer by having a method inside the OLE that reads it as such: srv getLastResult. In effect I have to do this: srv func: param; getLastRes. It seems to me that methods with no parameters answer correctly. Its only if you have a parameter that it does not work properly. This does not work. =============== MyserverIserver createObject: 'Myserver.server' ----> No such interface. 16r4002 MyserverIserver new. ----> No such interface. 16r4002 Any ideas or things to check would be appreciated... Costas |
Costas
You wrote in message news:[hidden email]... > ... > Just wanted to report back to you what works and what doesn't work and > see if there is anything else I should check or test. > > Assume the method to invoke is func: param > > This always works: > =============== > > srv := IDispatch createObject: 'Myserver.server'. > srv invoke: 'func' with param. That is the preferred way to invoke via IDispatch, though I would only use IDispatch where it is the only thing available, or where the object model being used is very large and one only wants to use part of it. Actually I think the latter is pretty dubious too, since Dolphin Pro's image stripper will do a good job of removing most of the stuff that isn't used, so the cost is mainly a larger (perhaps much larger if the object model is for the HTML DOM) development image. > > This partially works > =============== > srv := IDispatch createObject: 'Myserver.server'. > srv func: param. > > The func executes correctly but always returns nil. I get the answer > by having a method inside the OLE that reads it as such: This goes through DNU (#doesNotUnderstand:) processing of IDispatch. It doesn't use any type information other than a look up of the name (taken to be the primary keyword of the selector that accompanies the message which was not understood), i.e. a call to IDispatch>>GetIdsOfNames(). It is frankly unreliable, partly because in Smalltalk we can't distinguish a property access from a method invocation, and partly because the approach is simple. A better job could be done by dynamically looking up type information in the object's type library (if available), but as I don't really believe this is the correct approach for anything but scripting languages (for one it is dog slow), I am not terribly keen to encourage its use. > srv getLastResult. > > In effect I have to do this: > > srv func: param; getLastRes. I think that is most unsatisfactory. Generally speaking DNU access will work, but it depends on the automation server. I can't say why in particular it is failing in this case. > It seems to me that methods with no parameters answer correctly. Its > only if you have a parameter that it does not work properly. That gives a clue. As I mentioned above, Dolphin is unable to distinguish between a property access and a method invocation. Therefore if there are no arguments it assumes that the call is either a property read (propget) or method invocation, and passes both flags to the This always works because VB isn't able to distinguish this case either, e..g: X = Obj.PropOrMethod ' Am I a method invocation with a return value, or a property read, VB doesn't know Hence one is specifically allowed to pass both DISPATCH_PROPERTYGET and DISPATCH_METHOD together in a call to IDispatch::Invoke(). It is up to the server to work out whether a property access or method invocation is being attempted However, VB _is_ able to distinguish between a property write (propput) and a method invocation Obj.Prop = 2 ' Assignment allows VB to know this is a property write Obj.Method(2) Note that in the case of the latter VB still doesn't know if this is an read of an indexed property or a method with one argument (I can't remember whether the brackets are needed or not in this case; VB syntax is so inconsistent. In Smalltalk we can't distinguish this case, because we can only assign to Smalltalk variables, not properties of objects. An invocation of a simple instance variable setter method in Smalltalk, for example, looks exactly like a one argument keyword message send, because that is what it is. Thus the DNU handler for IDispatch has no completely reliable way of knowing whether to pass DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF, DISPATCH_METHOD, or even DISPATCH_PROPERTYGET (since the argument might be the subscript accompanying an indexed propget). Passing combinations of these flags seems to work for some cases with some servers, but it is not specifically permitted in the spec. Dolphin passes both DISPATCH_METHOD and DISPATCH_PROPERTYPUT, which some automation servers don't like. Another issue is with the handling of the return value. A method in an interface may pass its return value through an output argument rather than through the return value holder specifically provided for this purpose. Dolphin's type library analyzer (used by the AX Component Wizard to generate interface wrapper classses) can spot this and do the necessary to generate a suitable wrapper method, but it will be more difficult to call the methods successfully through IDispatch. BTW: I would recommend looking at the IDL which Dolphin can reverse engineer from a type library (The ''Browse IDL' command on the main context menu of the . You may see that components built exclusively with VB, etc, tend to treat a lot method arguments as in-out parameters. These are most awkward to wrap successfully because one must assume the argument has to be passed by reference, and forms an output from the method too. It is often necessary to hand code a suitable wrapper method for such interface methods. Try and avoid implicit or explicit By-Ref parameters to COM objects. in-out parameters are usually a bad idea, but that is another topic. > This does not work. > =============== > > MyserverIserver createObject: 'Myserver.server' > ----> No such interface. 16r4002 > > MyserverIserver new. > ----> No such interface. 16r4002 > > Any ideas or things to check would be appreciated... > Take the error report literally; the server is telling you it does not support the interface requested, a decision it makes on the basis of the IID (the GUID that uniquely identifies the COM interface). That is almost certainly because you have rebuilt the automation server since you generated MyserverIserver using the AX Component Wizard. VB, for example, changes the IID every time one rebuilds a server, at least by default. I imagine other Microsoft tools may be similar. It is necessary to turn on 'Binary Compatibiliy', or some similar option, to prevent this happenning, or alternatively to regenerate the interface in Dolphin every time the server is rebuilt. One other approach is to construct the IDL separately, run it through MIDL, import (reference) the resulting typelib into VB, and then declare the COM objects as implementing interfaces from that type lib. This allows much more control over the definitions of the methods, and also provides useful documentation (the IDL). Regenerating an interface from the current type library information is is pretty easy in Dolphin: MyserverIserver typeInfo generate Regards Blair |
"Blair McGlashan" <[hidden email]> wrote:
>> This does not work. >> =============== >> >> MyserverIserver createObject: 'Myserver.server' >> ----> No such interface. 16r4002 >> >> MyserverIserver new. >> ----> No such interface. 16r4002 >> >> Any ideas or things to check would be appreciated... >> > >Take the error report literally; the server is telling you it does not >support the interface requested, a decision it makes on the basis of the IID >(the GUID that uniquely identifies the COM interface). That is almost >certainly because you have rebuilt the automation server since you generated >MyserverIserver using the AX Component Wizard. VB, for example, changes the >IID every time one rebuilds a server, at least by default. I imagine other >Microsoft tools may be similar. >............... In an effort to figure out the problem, I used another COM which worked fine by sending it message new. However I discovered something interesting in the process. This COM's _guid and clsid were the same. My COM's _guid and CLSID are NOT the same. I am not sure if this is significant. I then tested both COMs using VB. I defined it as a COM Reference (and declared it accordingly. It executed fine. (This is the equivalent of what Dolphin does with the wizrd) Dim srv As new Myserver.server srv.func("whatever") (In VB you can also use: set srv = createObject("Myserver.server") which is the equivalent of #createObject: in Dolphin ) I then edited the registry and deleted any keys refering to myserver. I recompiled and marked the "Generate new CLSID/GUID" in Visual Foxpro (My COM object is VFP). I then used a fresh image of Dolphin4.0 and created the Myserver.server class using the Dolphin Wizard. Then I debugged it: self halt. MyserverIserver new. The failure of my COM is exactly at the point where the CreateInstance method is called: COMInterface class>> onCLSID: aCLSID outerIUnknown: pUnkOuter hostName:hostNameString licenseKey: licenseString ...<snipcode>... hr := pFactory CreateInstance: pUnkOuter riid: self iid ppvObject: pUnk. So here (self iid) uses the GUID from the list below. Since I can't trace any further I can't tell why it fails if the CLSID is not equal to GUID. Here are the ids I located for MyServer in the registry. '{FEC38E94-3EBB-4E2B-ABF8-083C79D7E0B9}' guid/interface '{E817962D-F94B-4EF1-AF5C-ECAA32AEBE57}' clsid/clsid '{31270B36-F532-46DA-80E2-FA4764375175}' typelib/interface '{00020424-0000-0000-C000-000000000046}' Proxy for typelib I believe I am doing everything correctly. Could it be that #CreateInstance: riid:ppvObject: is assuming that the iids must be equal? Also you were going to tell me how I can look at an IDL file but somehow you never finished the sentence. You said: " (The ''Browse IDL' command on the main context menu of the . )". I looked for a Browse IDL everywhere. I could not find it. Sorry if I am persistent because this COM I made works with other languages and I would like to make sure its not some issue with Dolphin. Regards, Costas |
Blair,
I forgot one more important point. The COM server that works is very similar to my server (itsalso VFP made). When instantiated with #new, all the methods work properly within Dolphin, including methods with parameters that return variant values [in, out]. Costas |
In reply to this post by Costas Menico-2
Costas,
Sorry that I can't help you with the problem you are having, but at least I know where you can find the 'Browse IDL' command. Open the ActiveX control browser on the control that you are interested in. Then choose Help\Show IDL from the menu. Sincerely, Mikael Svane [hidden email] |
"Mikael Svane" <[hidden email]> wrote:
>Sorry that I can't help you with the problem you are having, but at least I >know where you can find the 'Browse IDL' command. Open the ActiveX control >browser on the control that you are interested in. Then choose Help\Show IDL >from the menu. Mikael (and Blair), Thanks... As a matter of fact the Dolphin IDL Browser does not work right on this component either. It does not produce any of the interface methods. I downloaded the Microsoft IDL viewer from http://www.microsoft.com/com/resources/oleview.asp and tried it. Microsoft's works fine and shows all the interface methods. Blair, I hope you are reading this because in my programmer's paranoia I tested my component, on the same machine, with Dolphin 3.0 and it works like a charm. Even the answers come back correctly (except D3 replies an Array with the original parameter at: 1 and the answer at: 2). And I get a speed increase of 400%. I hope you agree with me that this may be an issue witht Dolphin 4.0. (I feel like an idiot for not testing with D3.0 from the start and saved myself all this debugging effort. But I did learn a lot<g>). Regards, Costas |
Costas
If you send me a copy of the component then I will investigate. Regards Blair "Costas Menico" <[hidden email]> wrote in message news:[hidden email]... > "Mikael Svane" <[hidden email]> wrote: > > >Sorry that I can't help you with the problem you are having, but at least I > >know where you can find the 'Browse IDL' command. Open the ActiveX control > >browser on the control that you are interested in. Then choose Help\Show IDL > >from the menu. > > Mikael (and Blair), > > Thanks... As a matter of fact the Dolphin IDL Browser does not work > right on this component either. It does not produce any of the > interface methods. I downloaded the Microsoft IDL viewer from > http://www.microsoft.com/com/resources/oleview.asp and tried it. > Microsoft's works fine and shows all the interface methods. > > Blair, I hope you are reading this because in my programmer's paranoia > I tested my component, on the same machine, with Dolphin 3.0 and it > works like a charm. Even the answers come back correctly (except D3 > replies an Array with the original parameter at: 1 and the answer at: > 2). And I get a speed increase of 400%. > > I hope you agree with me that this may be an issue witht Dolphin 4.0. > (I feel like an idiot for not testing with D3.0 from the start and > saved myself all this debugging effort. But I did learn a lot<g>). > > Regards, > > Costas |
Free forum by Nabble | Edit this page |