help! GPFs when I load/unload DLLs with reportbuilder units
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
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
This discussion has been closed.
Comments
- 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
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
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
- 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