Aaron wrote:
> The biggest annoyance with the DLL idea is our dependance upon
> polymorphism
> through the 'is' operator... I haven't experimented with
> packages, but I understand
> this alleviates this particular problem...
Yes, Packages fixes this but there other solutions. To understand why the
problem is there, you need to understand how 'is' works internally and why
that breaks with pure DLLs as opposed to packages which do some extra magic.
When you do a <SomeObject> is <SomeClass> call, what the 'is' operator does
is grab the TClass value for <SomeObject> (which is actually the VMT
pointer - that's what a TClass reference actually is) and compares that
value to the <SomeClass> TClass value.
Now each TClass contains a reference to it's parent TClass (i.e. the one it
inherits from) so the 'is' operator will backward chains through the TClass
hierachy for <SomeObject> until it walks off the list at TObject (and
returns False) or finds a matching TClass value (and returns True).
The code for all this is in System.pas _IsClass for those who are curious.
Now this hierachy of TClass relationships is built at Link time based on the
known classes linked into the given EXE or DLL.
When you compile a stand-alone DLL (i.e. not a package), it links in it's
own private copy of all the VCL code and classes and any of your base
classes referred to in that DLL. This is a _seperate_ Class hierachy list
with it's own VMT pointer values. A copy of the same code (unless you have
versioning problems :-) is at the end of each VMT method but it's a
different _pointer_ value.
If you perform an <SomeObject> 'is' <SomeClass> test in your EXE code on an
<SomeObject> created in your DLL code, it will walk up the DLLs
inheritance's hierachy (which <SomeObbject> has VMT pointers into) looking
for matchs with a TClass value from your EXE's TClass inheritance hierachy
and this will fail since none of the pointer values will match.
This is a fairly classic aliasing problem. Delphi has a similar issue with
internal Heap aliasing which is why SharedMM is necessary for passing
strings between DLLs and EXEs.
There are a two of ways around this:
1) You can use packages. When Delphi introduced packages they added an extra
level of indirection into the parent TClass VMT pointer chain. You can see
this by comparing the pre-packages Delphi System.pas code with the current
System.pas code.
When you call LoadPackage, it performs the usual DLL LoadLibrary calls and
then (amongst other 'magic') looks into the TClass hierachy of the package
and merges in and redirects the VMT class pointers so that all TObjects
created by DLLs or EXEs _share_ the same VMT TClass list as the original
EXE.
Presto, the TClass aliasing problem is solved.
2) Without packages, you can implement your own 'is' style operator which
compares via _ClassNames_ (i.e. strings), not via TClass values (i.e. VMT
pointers). This will succeed even across an EXE/DLL boundary. It will be a
bit slower that Delphi's hand-tuned assembler VMT pointer version but it
_will_ work.
Writing an IsClassName(SomeObject: TObject; SomeClass: TClass) routine is
left as an exercise for the reader.
TTFN,
Paul.
---------------------------------------------------------------------------
New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
Website: http://www.delphi.org.nz