[fpc-pascal] support for using anactivex

Ludo Brands ludo.brands at free.fr
Thu May 26 10:21:28 CEST 2011


The late binding method is more robust against interface changes than early
binding. Example: changing dispids won't affect late binding. Once a com
object is deployed, normally interfaces aren't modified (other than adding
new methods with new dispids) but new interfaces are added. Reason why there
are so many interfaces call ISomething2 or ISomething_V2. As long as you are
in the development phase, it is just a matter of talking to your collegues,
isn't it?  
The decision on early or late binding is in most cases determined by the
overhead late binding is causing. If this is an in-process com object late
binding is many times slower than early binding. Early binding will use
VTABLE info and call the methods directly. For out-of-process objects the
performance difference is less striking because of data marshalling.

IFileZapper and IFileZapperDisp are 2 descriptions for the same interface
(dual interface). IFileZapper allows for direct access to the methods and
properties. Dispinterface is used for late binding and is used to avoid
querying the interface to discover methods.

Because of data marshalling you can only use datatypes that can be
marshalled. Strings have to in the BSTR format which is compatible with fpc
WideString. Take a look at Activex.pp. There is a table just before the
definition of VT_EMPTY (line 296). Types marked with [S] can be marshalled
automatically (ie late binding). 

Ludo




-----Message d'origine-----
De : fpc-pascal-bounces at lists.freepascal.org
[mailto:fpc-pascal-bounces at lists.freepascal.org] De la part de Roberto
Padovani
Envoyé : mercredi 25 mai 2011 22:52
À : FPC-Pascal users discussions
Objet : Re: RE : RE : RE : RE : RE : RE : [fpc-pascal] support for using
anactivex


Always thanks!

Given your evident experience on this matter, I kindly ask your advice on
what is best to do.

opt 1) create a fpc class with some pascal style methods, which in their
implementation use variants and call the IDevice class with late-binding
..... meaning that there is no compiler check and if my collegue changes the
dll, then I have to change these implementations

opt 2) in a reference of those you sent me, there is some example code from
which I take the lines below. In the tlb conversion unit, the interface and
dispinterface of the class are some replicated. Then also the eventinterface
is defined. The main interface class is defined without and with dispids.
With the dispids, only the properties are defined and not the methods.

  IFileZapper = interface(IDispatch)
    ['{2E2FC5E0-5C0E-4C4F-8CC1-D9F6C5A92BA6}']
    function Get_Directory: WideString; safecall;
    procedure Set_Directory(const Value: WideString); safecall;
    function Get_FileMask: WideString; safecall;
    procedure Set_FileMask(const Value: WideString); safecall;
    procedure BringToFront; safecall;
    property Directory: WideString read Get_Directory write Set_Directory;
    property FileMask: WideString read Get_FileMask write Set_FileMask;
  end;

  IFileZapperDisp = dispinterface
    ['{2E2FC5E0-5C0E-4C4F-8CC1-D9F6C5A92BA6}']
    property Directory: WideString dispid 1;
    property FileMask: WideString dispid 3;
    procedure BringToFront; dispid 10;
  end;

  IFileZapperEvents = dispinterface
    ['{7B6F8ADD-7980-4A35-838B-E1600C43D29E}']
    procedure OnSelectionChanged; dispid 1;
    procedure OnDirectoryChanged(const DirName: WideString); dispid 2;
  end;

Is this somewhat the same thing as the wrapper of option 1? If I write all
of this conversion (and, by the way, how to convert C++ data types to
pascal?? widestring ?), then how can I use it?

In the end, maybe the wiki page about COM interfaces should be update to
something more than 'Word.Application.NewFile'. I can't share the activex I
have, otherwise it would be a good example to see something useful to start
with.

Roberto

2011/5/25 Ludo Brands <ludo.brands at free.fr>:
> Using variants you can transparently "walk" along the exposed objects. 
> The variant contains the Idispatch of the object and gets the exposed 
> methods at runtime. Properties are implemented as get and put methods 
> or just get methods for read only properties.
>
> If you have something like
> Itransducers = interface
>  ..
>  property transducer[Index:integer]:Itransducer;
> end;
>
> Then you would do
> transducer := transducers.transducer[index];
>
> transducer := transducers[index];  works only if transducer is the 
> default property for Itransducers. I'm not sure if fpc supports this.
>
> Ludo
>
>
> -----Message d'origine-----
> De : fpc-pascal-bounces at lists.freepascal.org
> [mailto:fpc-pascal-bounces at lists.freepascal.org] De la part de Roberto 
> Padovani Envoyé : mercredi 25 mai 2011 19:34
> À : FPC-Pascal users discussions
> Objet : Re: RE : RE : RE : RE : RE : [fpc-pascal] support for using an
> activex
>
>
> 2011/5/25 Ludo Brands <ludo.brands at free.fr>:
>> The code in article 
>> http://www.informit.com/articles/article.aspx?p=130494&seqNum=5 goes 
>> a long way in doing what you want to do. Unit Eventsink does pretty 
>> much of the legwork. You should remove the procedure register since 
>> that is the Delphi way to get a component on the toolbar. Remove also 
>> the {$IFDEF VER100} and {$ENDIF}. The unit actually includes the code 
>> for InterfaceConnect!!
>
> found that! great!
>
>
>> As for the tlb conversion, in your case
>>
>> IEventIntfEvents = dispinterface
>>  ['{168F5642-5751-49F5-9AA4-B8A7A5F6A5B8}']
>>  end;
>>
>> should do (that is for the events part). AFAIK the procedure and 
>> dispid definitions are only needed for the server. You are only 
>> concerned with dispid's. No need to create prototypes for
>> OnCommChanged() etc. EventSink1Invoke would be a simple case DispID 
>> of
>>  1: // do CommChanged
>>  2: // do StatesChanged
>> ...
>> end;
>>
>>
>
> Now I am "wasting" time making the tlb pascal definitions. For the 
> event part I'm fine with the dispid's Until now I was calling the 
> activex method with variants, in and out, but now I discovered that 
> this IDevice class has a property like: property
> Sensors: ISensors;
> which inside is a list of items like   Sensor: ISensor.
>
> Can I read the sensores with a variant? Then, to see the fields inside 
> each sensor, I think a I need a class to do that... The activex has 
> all of these classes with the suitable dispinterfaces and uuids and so 
> on. But if I define
>     var device, transducers, transducer : variant;
> and create
>     device := CreateOleObject('Device');
> then, can i simply write the following ?
>     transducers := device.Transducers;
>     transducer := transducers[index];
>
>
> It's a long path until I get this stuff working...
>
> R#
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org 
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org 
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
_______________________________________________
fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal




More information about the fpc-pascal mailing list