L505 wrote:
If you choose for a dll system, I would choose Interfaces (and indeed,
don't pass strings, dyn arrays or classes)
Marc
I don't have much experience with interfaces and would like to learn more about
them. Can you import/export one to and from other languages? i.e. c++/c/etc.
Yes, Interfaces are language independent. They only define what
functions/procedures are available within an interface (and what calling
convention). An Interface itself has no data or code. I' is only a
"contract" that those functions are avalable.
The actual code is implemented by a delphi/FPC/C++ class.
As an example lets look at IStream:
Its methods are described at
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/istream.asp
and for FPC it is declared in packages\extra\winunits\activex.pp
IStream = interface(ISequentialStream)
['{0000000C-0000-0000-C000-000000000046}']
function Seek(dlibMove : Large_integer; dwOrigin: Longint;
out libNewPosition : Large_Integer): HResult; stdcall;
...rest skipped...
end;
This declaration defines only the interface. There is no code involved
here. You also see that this interface is derived from ISequentialStream
(just like you can have with classes) and this interface is identified
by the GUID 0000000C-0000-0000-C000-000000000046
Each interface should have its own GUID.
Now suppose you have some external function in some API/dll/whatever like:
function GiveMeAStream: IStream; stdcall; external;
then you can use it like:
var
Stream: IStream;
begin
Stream := GiveMeAStream;
if Stream.Seek(....) <> S_OK then ReportSomeError;
end.
You can call interface methods just like you call class methods,
independent on how it is implemented. The only thing you have to know is
that you can call it.
This is one side of the story. Now suppose you have an external function
in some API/dll/whatever like:
procedure PassMeAStream(aStream: IStream); stdcall; external;
Now are you the one who need to supply an interface. Luckely for us
there is a class which implements IStream (in classes.pp, unfortunately
comented out):
TStreamAdapter = class(TInterfacedObject, IStream)
....
end;
This looks like a normal class definition, only we tell now the compiler
that we also implement IStream. This means that all methods defined in
IStream have to exist in this class (or parent class) (remember "contract")
In this example the TStreamAdapter is a wrapper around a normal FCL
stream. So when we need to pass an IStream we can do something like:
var
FCLStream: TStream;
InterfaceStream: IStream;
begin
FCLStream := TMemoryStream.Create(...);
InterfaceStream := TStreamAdapter.Create(FCLStream);
PassMeAStream(InterfaceStream);
end.
this is equal to:
var
FCLStream: TStream;
Adapter: TStreamAdapter;
begin
FCLStream := TMemoryStream.Create(...);
Adapter := TStreamAdapter.Create(FCLStream);
PassMeAStream(Adapter);
end.
What you see here is that a class which implements an interface can be
stored in a variable of the classtype *or* of the interface type.
However, you have only access to the methods defined by the class *or*
the the interface.
For now I'll leave it here.
Marc
_________________________________________________________________
To unsubscribe: mail [EMAIL PROTECTED] with
"unsubscribe" as the Subject
archives at http://www.lazarus.freepascal.org/mailarchives