Board index » delphi » OOP-Plugins: sharing class definitions and objects betrween exe and dll

OOP-Plugins: sharing class definitions and objects betrween exe and dll

Hi!

Is it possible to share class definitions and objects and their
runtime type information (RTTI) between applications (exe) and dlls ?

Example:

in the application:
TBaseClass = class(TObject)
...
ExeObject = class (TBaseClass)
...
RegisterClass(TBaseClass);
RegisterClass(TExeClass);
ExeObject:= TExeClass(Create);

in the dll:
TBaseClass = class(TObject) // same as in exe
...
TDllClass = class (TBaseClass)
...
RegisterClass(TBaseClass);
RegisterClass(TDllClass);
DllObject:= TDllClass(Create);

After exchanging then objects between the .exe and the dll following
results:

In the exe:
ExeObject.InheritsFrom(TBaseClass): True
ExeObject.ClassType: TExeClass
DllObject.InheritsFrom(TBaseClass): False
DllObject.ClassType: TClass($address)

Stream.WriteComponent(ExeObject)
ExeObject2:= Stream.ReadComponent : OK
Stream.WriteComponent(DllObject)
DllObject2:= Stream.ReadComponent : Exception

In the dll:
ExeObject.InheritsFrom(TBaseClass): False
ExeObject.ClassType: TClass($address)
DllObject.InheritsFrom(TBaseClass): True
DllObject.ClassType: TDllClass

Stream.WriteComponent(ExeObject)
ExeObject2:= Stream.ReadComponent : Exception
Stream.WriteComponent(DllObject)
DllObject2:= Stream.ReadComponent : OK

Is there any way to exchange the RTTI between the exe and the dll so
that following resultts:
In the exe and the dll:
ExeObject.InheritsFrom(TBaseClass): True
ExeObject.ClassType: TExeClass
DllObject.InheritsFrom(TBaseClass): True
DllObject.ClassType: TDllClass

Thanks.

 

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


Im Artikel <39a1fb89.1715...@news.btx.dtag.de>, matthias.faulst...@t-online.de
schreibt:

Quote
>Is it possible to share class definitions and objects and their
>runtime type information (RTTI) between applications (exe) and dlls ?

Yes, if you make the DLL a runtime package.

DoDi

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


Hi!

In between, I found an example program which demonstrates this
mechanism.
(http://delphimag.com/features/1999/06/di199906xp_f/di199906xp_f.asp)

It will work only, if the base class will be capsulated in a
runtime-package. This package requires (actually) the Delphi vcl50.dcp
runtime-package. The main exe program and all add-in-packages have to
be linked against this base-package.

But what happens, if I distribute a program compiled now with Delphi 5
and later (when e.g. Delphi 6 is actual) someone wants a new add-on?
Then the new package and the base package then become linked against
vcl60.dcp or something like this. I cannot imagine, that this add-on
package will work with the program and the base package compiled with
Delphi 5. Is this true?

- Matthias

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


<matthias.faulst...@t-online.de> skrev i melding
news:39a76846.1695648@news.btx.dtag.de...

Quote
> But what happens, if I distribute a program compiled now with Delphi 5
> and later (when e.g. Delphi 6 is actual) someone wants a new add-on?
> Then the new package and the base package then become linked against
> vcl60.dcp or something like this. I cannot imagine, that this add-on
> package will work with the program and the base package compiled with
> Delphi 5. Is this true?

Yes, it's true. If you really want to have some flexibility, you don't share
classes between .exe's and .dll's, packages or not.
I've found that Interfaces are perfect for this scenario, where your actual
implementation of the object interfaces may be different in the modules.

It has more benefits, too, only the essential parts of the object
declarations are exposed. Simplify teamwork & allow real "black box"
behaviour. Moreover, you may use objects in other modules without knowledge
of anything but the interface declaration.

What you won't get by using interfaces, though, is the class inheritance
stuff (well, it may be simulated).
--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


Im Artikel <39a76846.1695...@news.btx.dtag.de>, matthias.faulst...@t-online.de
schreibt:

Quote
>But what happens, if I distribute a program compiled now with Delphi 5
>and later (when e.g. Delphi 6 is actual) someone wants a new add-on?
>Then the new package and the base package then become linked against
>vcl60.dcp or something like this. I cannot imagine, that this add-on
>package will work with the program and the base package compiled with
>Delphi 5. Is this true?

Then you have 2 options:

Develop the new add-on with D5, or rebuild the whole project with D6.

DoDi

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


On Sat, 26 Aug 2000 23:24:48 +0200, "Bj?rge S?ther"

Quote
<REMOVE_bsaether@THIS_online.no> wrote:
>Yes, it's true. If you really want to have some flexibility, you don't share
>classes between .exe's and .dll's, packages or not.
>I've found that Interfaces are perfect for this scenario, where your actual
>implementation of the object interfaces may be different in the modules.

I tested this and found, that there is still (minimum) one problem:
RTTI
Whether I use interfaces or classes, the dll and the exe have
different type information, so following funny (or not, if there is a
need for a successful test ) behaviour results:

example.
an exported procedure within a dll's source code:
procedure TestComponent(C: TComponent);
begin
   if C.InheritsFrom(TComponent)
   then ShowMessage('yes')
   else ShowMessage('no');
end;

called from an exe-Form with a TButton named Button1 like
   Lib:= LoadLibrary('interfacedll.dll');
   @TestComponent:= GetProcAddress(Lib, 'TestComponent');
   TestComponent(Button1);

will result in a "no" message, although a TButton-Component inherits
from TComponent.

Is there no chance to "copy" runtime type information from one module
to an other?

- Matthias Faulstich

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


<matthias.faulst...@t-online.de> skrev i melding
news:39ab82d5.15421014@news.btx.dtag.de...

Quote
> On Sat, 26 Aug 2000 23:24:48 +0200, "Bj?rge S?ther"
> <REMOVE_bsaether@THIS_online.no> wrote:

> >Yes, it's true. If you really want to have some flexibility, you don't
share
> >classes between .exe's and .dll's, packages or not.
> >I've found that Interfaces are perfect for this scenario, where your
actual
> >implementation of the object interfaces may be different in the modules.

> I tested this and found, that there is still (minimum) one problem:
> RTTI
> Whether I use interfaces or classes, the dll and the exe have
> different type information, so following funny (or not, if there is a
> need for a successful test ) behaviour results:

> example.
> an exported procedure within a dll's source code:
> procedure TestComponent(C: TComponent);
> begin
>    if C.InheritsFrom(TComponent)
>    then ShowMessage('yes')
>    else ShowMessage('no');
> end;

> called from an exe-Form with a TButton named Button1 like
>    Lib:= LoadLibrary('interfacedll.dll');
>    @TestComponent:= GetProcAddress(Lib, 'TestComponent');
>    TestComponent(Button1);

> will result in a "no" message, although a TButton-Component inherits
> from TComponent.

> Is there no chance to "copy" runtime type information from one module
> to an other?

AFAIK, No, but you could create a few helper functions:

function AInheritsFromB(A, B: TClass): boolean;
begin
  repeat
    result:=A.ClassName = B.ClassName;
    A:=A.ClassParent;
  until
    result or (A = nil);
end;

... one major problem is the Assign() and AssignTo() ethods of TPersistent,
who don't work because of type checking.

What you could do, of course, is to set the object's VMT pointer according to
the other module's corresponding one:

function TranslatedClassOf(Source, ClassInCurrentModule: TClass): TClass;
var
  Match : boolean;
begin
 // ClassInCurrentModule needs to be equal to, or descend from,
 // Source. That's the only way to get the proper Class pointer (=VMT)

  result:=ClassInCurrentModule;
  repeat
    Match:=Source.ClassName = result.ClassName;
    if Match then exit;
    result:=result.ClassParent;
  until
    Match or (result = nil); // ClassInCurrentModule did not inherit from
Source
end;

procedure ChangeVMT(A: TObject; B: TClass);
begin
  Pointer(Pointer(A)^):=B;
end;

...test this one:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ChangeVMT(Edit1, TObject);
  Caption:=Edit1.ClassName;
  ChangeVMT(Edit1, TEdit);
end;

...I don't know if I would recommend this, failures would bomb anything...and
I believe I should have written it under a Pseudonym. Such techniques are not
very popular amongst Delphi professionals ;^D

Great fun, though...
--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


Quote
<matthias.faulst...@t-online.de> wrote in message

news:39ab82d5.15421014@news.btx.dtag.de...

Quote
> Is there no chance to "copy" runtime type information from one module
> to an other?

While there may be a way I really doubt if one would want to use it. When
one has two separately compiled executables short of a complete comparison
of the type info tree for a given component one cannot be assured that the
definitions are identical. Thus any cross reference of a property or method
cannot be statically bound or even statically bound to a VMT position. The
references, of necessity, have to be entirely dynamic and bound only at
run-time.

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


"Bruce Roberts" <no.junk.please....@attcanada.net> skrev i melding
news:2VRq5.56776$qS3.113392@tor-nn1.netcom.ca...

Quote

> <matthias.faulst...@t-online.de> wrote in message
> news:39ab82d5.15421014@news.btx.dtag.de...

> > Is there no chance to "copy" runtime type information from one module
> > to an other?

> While there may be a way I really doubt if one would want to use it. When
> one has two separately compiled executables short of a complete comparison
> of the type info tree for a given component one cannot be assured that the
> definitions are identical. Thus any cross reference of a property or method
> cannot be statically bound or even statically bound to a VMT position. The
> references, of necessity, have to be entirely dynamic and bound only at
> run-time.

Bruce,
In this case you just can't pass objects across .dll/.exe boundaries. The
code used for calling methods in the.dll on objects created in the .exe stems
from the .dll's decklarations. If the two versions of the classes are
diverging, it goes all wrong. The only way to succeed is if the order of
fields and methods are in fact identical. That goes for Interfaces, as well,
but then only the interface declaration needs to match, not the actual
implementation. The only way to achieve full flexibility would be to use
dispatching interfaces (OLE/COM), whose methods & parameters are resolved at
runtime. This is very slow, though...

--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


Quote

>AFAIK, No, but you could create a few helper functions:

>function AInheritsFromB(A, B: TClass): boolean;
>begin
>  repeat
>    result:=A.ClassName = B.ClassName;
>    A:=A.ClassParent;
>  until
>    result or (A = nil);
>end;

I tested this (works well!) but found, that in my application one
solution in this direction only leads to the next problem.

It seems, that the main mistake in my concept is to try to make an
application expandable in the future only by adding add-on dll's or
packages regardless what kind of Delphi version is used for
compilation. This seems to be possible only, if the exe and the dll's
exchange nothing more then basic data types (integer, floating point
values etc).

The solution I will use now is to compile all data type objects into a
runtime package and link the exe and all add-ons against it.

Thanks all for your help!

- Matthias Faulstich

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


<matthias.faulst...@t-online.de> skrev i melding
news:39acc062.11013316@news.btx.dtag.de...

Quote
> It seems, that the main mistake in my concept is to try to make an
> application expandable in the future only by adding add-on dll's or
> packages regardless what kind of Delphi version is used for
> compilation. This seems to be possible only, if the exe and the dll's
> exchange nothing more then basic data types (integer, floating point
> values etc).

> The solution I will use now is to compile all data type objects into a
> runtime package and link the exe and all add-ons against it.

Yes, you're proboably right. The alternative would be to operate on
interfaces. If you use COM-compliant interfaces, you could even create
plugins with other compilers.

--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:OOP-Plugins: sharing class definitions and objects betrween exe and dll


Quote
>Yes, you're proboably right. The alternative would be to operate on
>interfaces. If you use COM-compliant interfaces, you could even create
>plugins with other compilers.

That seems work, but only with reduced spectrum, e.g. without any kind
of VCL streaming system usage.

If I share the object definition - regardless whether a complete class
defintion or an interface only - create an object, based upont this
defintion in a dll and pass it to the exe, then TObject.Classtype,
executed inside the exe,  will result in something like TClass($XXXX).
In this case, the interfase procedures / funktions will work, but e.g.
TStream.WriteComponent() and TStreamReadComponent as well will result
in an exeption.

Matthias Faulstich

Other Threads