Home General
New Blog Posts: Merging Reports - Part 1 and Part 2

help! GPFs when I load/unload DLLs with reportbuilder units

edited August 2006 in General
Hi All,

I'm really blocked by this issue... any help/advice would be very much
appreciated.

I'm getting a GPF from the use of the reportbuilder within my DLLs. I'm
building plugins to my main application, some of which will incorporate
reports. My application is MDI. I need for my plug-ins (forms) to be
DLLs (so they'll have different namespaces... allowing each to
occasionally have a form named then same).

To achieve that, I'm using a technique laid out in this page:
http://www.noxas.co.uk/SinglePkg/ (reverse "noxas" in the browser). The
strategy is to create a bpl package that contains all the libraries the
app and dlls will need (forms, controls, classes, messages, ...). The
EXE and DLLs are told to build with that package as the sole runtime
library (and the library path in delphi itself is set to only reference
the BDS/Project/BPL directory). The last task, for convenience, is to
put SysInit.Dcu in ${BDS}\Projects\BPL. It's the only unit that needs
to be referenced directly by all the EXEs and DLLs.


It all works. The plug-ins load and work remarkably well. However, if
I unload a dll (FreeLibrary) and then try to load it back in
(LoadLibrary), it GPFs every time if the dll contains reportbuilder
references.

I've learned through experimentation that it's only happening with the
reportbuilder components... and with every one of them that I try. I've
built a very small example to show it failing. Source and executables
can be downloaded from http://eradilla.com/rptbldrDLL.zip (reverse the
domain name, please... trying to avoid the lazy spammers ;).

Any help would be very greatly appreciated, I'm really stuck on this
issue.


Clif D.
reversethedomain@tdrahnaed.com



--- posted by geoForum on http://delphi.newswhat.com

Comments

  • edited August 2006

    - the concept of a plug-in is that you have some code/classes that you want
    to dynamically load and use.

    - the Delphi package architecture was designed to accomodate this.

    - the Delphi IDE and ReportBuilder itself are both good examples of
    artchitectures that support plug-ins. In the Delphi IDE you can
    install/uninstall packages that make components and features available. You
    can install/uninstall the ReportBuilder packages and no AV's will occur. As
    an example, you can uninstall the ReportBuilder Dade and RAP packages from
    the Delphi IDE and the report designer will no longer display the Data and
    Calc tab. Then re-install them and they will re-appear. You can also install
    DADE plug-ins to make additional session types appear, install RB export
    add-ons to make additional export devices appear, install custom components,
    such as the sample checkbox, that can appear on the report designer's
    component palette, etc.


    - ReportBuilder uses a lot of internal class registrations to manage the
    plug-ins classes that it uses. The units contain Initialization/Finalization
    section code to register/unregister classes. The architecture depends upon a
    unit only being loaded/unloaded a single time.

    - With the .dll architecture you are trying to use, the same units (the same
    code/classes) are getting loaded multiple times (into the single process
    space). That is causing the issues.



    --
    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited August 2006
    Nard,

    Thanks for the quick reply. My original version of the app used the delphi
    BPLs, but I ran into a case in which I needed to make 3 plug-ins, each of
    which is a very slight alteration to the original, complicated plug-in. As
    the development of these plug-ins is expected to continue, I didn't want to
    make 3 cut/paste copies of the original, which I'd be required to do given
    that the units and classes would be required to have different names. Using
    the DLLs is what allows me to avoid having to triple the work for each
    change to the plug-in.

    It may be fruitless, but I'll probably spend a few hours trolling through
    the reportbuilder code hoping to find a culprit that I can fix. Otherwise
    I have a hard decision to make: triple my development time on this (and the
    upcoming plug-ins) or swapping to a new reporting system. Both are equally
    depressing results :(

    I did have one additional question... In your reply you said


    But I can sucessfully load 3 DLLs, each with references to the ReportBuilder
    units. At that point, I've already loaded them multiple times haven't I?
    It only dies when I unload and reload any one of the DLLs. Have I missed
    your point?

    And finally, for my own sanity... do I stand a chance in heck of finding a
    way to make it work or are you certain that the nature of the units preclude
    their use in DLLs ?

    Clif


  • edited August 2006
    Aha!

    I got to thinking about why I could load 3 DLLs with the report builder
    units and not have a collision, but if I unloaded them and tried to load
    them back it would fail. That implies that as long as there's one around to
    hold on to whatever memory has been allocated, it might be good to go.

    I created a new DLL that had very little other than a reference to ppDB
    (picked at random). I load it when the app boots and I never let go of it.
    Now the plug-ins will load, unload, and load again with immunity (or so it
    would seem). I've run it through several iterations and run reports at
    various stages. It seems to be working.

    Very curious indeed....

    Clif





  • edited September 2006


    - With the plug-in BPL approach you need to create a base ancestor class
    (TmyPlugInBase) and then descedant classes (TMyPluginA, TMyPluginB, etc).
    Put the TmyPlugInBase class in a separate unit and package
    (myPlugInCommon.dpk). Then put TMyPluginA in another separate
    package(myPluginA.dpk) that 'requires' myPlugInCommon.dpk. With that
    approach you can create and modify many plug-ins that use/require the same
    base functionality.

    -My guess is that when the .dll's load, the unit initializations register
    the classes many times and the duplicate registerations are perhaps
    ignored - so everything is ok. However, when the unload occurs, the classes
    are unregistered - which sort of pulls the rug out from under the whole app.

    - I see in your next post that you have discovered a work around - so now
    you know more than me :)

    --
    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com



    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
This discussion has been closed.