1
votes

I have created a Package and i want to use the BPL File of my Package ...

My Package have VCL.dcp and RTL.dcp as Required libraries , i load this Package in my application without any errors but when i want to unload it , an Access Violation shown !

If i Build my Application with Run-Time Packages ( "vcl" and "rtl" ) , Access Violation not shown !

alt text

What is this mean ?! My Application need VCL and RTL Libraries to Load BPLs ?! I want to Load my Package like a DLL File , is there any solution ?

I`m using Delphi 2010

thanks a lot ...

5
RTL and VCL packages are the core Delphi packages, if you use Delphi RTL classes or VCL components in your package, you need those two packages too. What does your package do? How do you use the package in your application?vcldeveloper
@vcldeveloper : My Package contains an unit with a form , i want to load the form dynamically , i use LoadPackage to load my BPL file , it loads successfully , and i can show the Form included in package , but when i call UnloadPackage function to Unload package , AFTER unloading the package , i will get an AV !! If i build my application with run-time packages ( vcl and rtl ) , AV not shown ... ! , i want to use my package without needing of VCL and RTL Run-Time Packages !Mahmood_N

5 Answers

8
votes

Your BPL requires the RTL and VCL packages. If your Application doesn't require them, then that means the RTL and VCL units are compiled into your EXE file. When your EXE loads your BPL, you now have two copies of the RTL and VCL units — one set of copies comes from within the EXE, and the second copies come from the RTL and VCL packages that your package implicitly causes to be loaded.

Delphi isn't intended to accommodate that situation. It's possible that you have memory that was allocated by one RTL and attempted to get freed by the other RTL. Or there might be function pointers in the EXE that refer to functions that were in the VCL package.

I see three options for you:

  1. Compile your EXE to use packages. Specifically, it should require the same RTL and VCL packages that your BPL requires.

  2. Make your BPL not require any other packages. If it doesn't require RTL and VCL, then any RTL and VCL units that your package uses will get compiled into your BPL. You'll end up with two separate copies again, but it should work better since neither copy will think it's supposed to be shared.

  3. Load your package like a real DLL instead of like a package. You said you wanted to use it like a DLL, so do that. Use LoadLibrary, and then use GetProcAddress to get whatever functions you want to call. If you go this route, it's probably better to not make your code be a package at all. Make it a DLL, and export functions that only use parameter types that you'd expect to find in other DLLs, like integers, character pointers, and record pointers, not strings or objects.

It should be clear that the first option is the easiest. The second could probably work, and it sounds like that's the way you'd prefer, but I expect it will generate more headaches before it finally works. The third option is best if you'll ever have to use other development environments during the lifetime of this project.

1
votes

What have your package inside?
What work do you do with it?
How do you charge and discharge? What's in it?

What do you do with the package before unload it?
When you Unload it, all the objects/forms/components/... that yo've used is released?

ADDED: I Think that you are using anything of the package when you try to Onload. This is the reason of AV.

In an EXE compiled without runtime package, I load the package:

  OutputDebugString(PChar('Loading the package'));
  hand := LoadPackage('r:\rrrrrrr\Package1.bpl');

I Unload the package with this code:

  OutputDebugString(PChar('Ready to Unload Package'));
  UnloadPackage(hand);
  OutputDebugString(PChar('Unloaded'));

The package has a unit with a form (form1) and a unit Init.pas, for initialization like this:

unit Init;

interface

// prototipos
procedure Start_P;
procedure Finish_P;

implementation

uses
  Unit1, Windows;

procedure Finish_P();
begin
  OutputDebugString(PChar('Finish_P   form free'));
  Form1.Free;
end;


procedure Start_P();
begin
  OutputDebugString(PChar('Start_P   Creating form'));
  Form1 := TForm1.Create(nil);
  Form1.Show;
end;

Initialization;
  Start_P();

Finalization;
  Finish_P();

end.

The package is loaded and the form visualized without problems, and the same with the operation of Close and Unload. The project is compiled with "Build with rutime packages" unchecked.

Can you post any code.

The result of OutputDebugString is this (no AV error):

[2644] Loading the package
[2644] Start_P Creating form
[2644] Ready to Unload Package
[2644] Finish_P form free
[2644] Unloaded

Regards.

1
votes

Thanks for your helps ...

I put an example of my package and my Application here to Find what is the problem !

We have a package without requiring to Run-Time Packages like VCL and RTL , in other words i removed all libraries from the Requires section in my package : alt text

my package contains a form with code below :

unit MyUnit;

interface

uses
  Windows, Forms, StdCtrls, Buttons, Controls, Classes, Dialogs;

type
  TMyForm = class(TForm)
    MyLabel: TLabel;
    MyEdit: TEdit;
    PostBtn: TBitBtn;
    procedure PostBtnClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MyForm: TMyForm;

implementation

{$R *.dfm}

function ShowForm(FCaption, LCaption : String) : String;
var
 F : TMyForm;
begin
 F := TMyForm.Create(nil);
 try
  F.Caption := FCaption;
  F.MyLabel.Caption := LCaption;
  F.ShowModal;
 finally
  Result := F.MyEdit.Text;
  F.Free;
 end;
end;

procedure TMyForm.PostBtnClick(Sender: TObject);
begin
 if MyEdit.Text <> '' then
  Close
 else
  ShowMessage('Please Enter Value !');
end;

exports
 ShowForm;

end.

I Load this Package and Call ShowForm Function and then Unload package :

var
 ShowF : function(FCaption, LCaption : String) :  String;
 MyPkg : HMODULE;
 FC, LC : String;
begin
 MyPkg := LoadPackage(ExtractFilePath(Application.ExeName)+'MyPackage.bpl');
 FC := 'Enter Value ... ';
 LC := 'Value : ';
 if MyPkg <> 0 then
  begin
   try
    @ShowF := GetProcAddress(MyPkg, 'ShowForm');
    if Assigned(ShowF) then
     Edit1.Text := ShowF(FC, LC)
    else
     ShowMessage('Function not found !');
   finally
    UnloadPackage(MyPkg);
   end;
  end;
end;

After the Procedure above done , the AV Shows !

@Neftalí : If I just do loading and unloading the Package , no AV Shows , but i think that is because i don`t call some routines or objects or ... that they need VCL or RTL Libraries , if i use objects and functions and ... of this package , after using them i will get an AV ... is it true ?!

If I Build my application with Run-Time package ( VCL and RTL ) no AV will shown !

I`m confusing !! , I want to use an BPL package without any Run-Time package needed ...

thanks a lot ...

0
votes

Yes, if you want to use runtime packages in your application you have to build it with runtime packages, and then it requires them (links statically with them).

The solution to your problem depends on what the problem actually is (which is unclear at the moment).

0
votes

Ohhhhh, great oversight/neglect (mine).
With the code that you have posted, made a simple change a test it (use PChar).

function ShowForm(FCaption, LCaption : String) : PChar;  
...

    Result := PChar(F.MyEdit.Text);
  ...

The same when you define the sitaxis of the function:

 ShowF : function(FCaption, LCaption : String):PChar;

Test it and say the result.

Regards.