BPL文件需要运行时包!

时间:2010-11-17 15:22:19

标签: delphi delphi-2010 packages bpl

我创建了一个包,我想使用我的包的BPL文件...

我的软件包将VCL.dcp和RTL.dcp作为必需的库,我在我的应用程序中加载此软件包时没有任何错误,但是当我想卸载它时,显示了访问冲突!

如果我使用运行时软件包构建我的应用程序(“vcl”和“rtl”),则不显示访问冲突!

alt text

这是什么意思?!我的应用程序需要VCL和RTL库来加载BPL吗?我想像DLL文件一样加载我的包,有什么解决方案吗?

我正在使用Delphi 2010

非常感谢...

5 个答案:

答案 0 :(得分:8)

您的BPL需要RTL和VCL套餐。如果您的应用程序需要它们,则表示RTL和VCL单元已编译到您的EXE文件中。当您的EXE加载BPL时,您现在有两份的RTL和VCL单元 - 一组副本来自EXE,第二份副本来自您的包的RTL和VCL包隐含地导致被加载。

德尔福无意适应这种情况。您可能拥有一个RTL分配的内存,并试图被其他RTL释放。或者,EXE中可能存在引用VCL包中的函数的函数指针。

我为您看到三个选项:

  1. 编译您的EXE以使用包。具体来说,它应该需要您的BPL所需的相同RTL和VCL包。

  2. 让您的BPL 需要任何其他套餐。如果它不需要RTL和VCL,那么您的包使用的任何RTL和VCL单元都将被编译到您的BPL中。您最终会再次使用两个单独的副本,但它应该更好用,因为两个副本都不会认为它应该被共享。

  3. 像真正的DLL一样加载您的包,而不是像包一样。你说你想像DLL一样使用它,所以这样做。使用LoadLibrary,然后使用GetProcAddress获取您要调用的任何函数。如果你走这条路,最好不要让你的代码成为一个包。使它成为DLL,并导出仅使用您希望在其他DLL中找到的参数类型的函数,如整数,字符指针和记录指针,而不是字符串或对象。

  4. 应该很清楚,第一个选项是最简单的。第二个可能会起作用,听起来就像你喜欢的那样,但我预计它会在它最终起作用之前产生更多的麻烦。如果您在此项目的生命周期内必须使用其他开发环境,则第三种选择最佳。

答案 1 :(得分:1)

你的包裹里面有什么?
你用它做了什么工作?
你如何充电和放电?里面是什么?

在卸载之前你怎么处理它呢? 当你卸载它时,你所使用的所有对象/表单/组件/ ...都被释放了?

ADDED:我认为您在尝试Onload时正在使用该软件包的任何内容。这就是AV的原因。

在没有运行时包编译的EXE中,我加载了包:

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

我使用以下代码卸载软件包:

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

该软件包的单元格式为( form1 ),单元格式为 Init.pas ,初始化如下:

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.

加载包并显示表单没有问题,与关闭和卸载操作相同。该项目使用“使用rutime包构建”未选中进行编译。

你能发布任何代码吗?

OutputDebugString的结果是这个(没有AV错误):

[2644]装入包裹 [2644] Start_P创建表单
[2644]准备卸载包裹 [2644] Finish_P表格免费
[2644]已卸载

问候。

答案 2 :(得分:1)

感谢您的帮助...

我在这里提供了我的包和我的应用程序示例,以找出问题所在!

我们有一个包,不需要像VCL和RTL这样的运行时包,换句话说,我从包中的Requires部分删除了所有库: alt text

我的包中包含一个包含以下代码的表单:

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.

我加载此包并调用ShowForm函数,然后卸载包:

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;

在上面完成的步骤之后,AV显示!

@Neftalí:如果我只是加载和卸载软件包,没有AV显示,但我认为这是因为我没有调用一些例程或对象或......他们需要VCL或RTL库,如果我使用这个包的对象和功能以及......使用后我会得到AV ... 这是真的吗?!

如果我使用运行时包(VCL和RTL)构建我的应用程序,则不会显示AV!

我很困惑! ,我想使用BPL包而不需要任何运行时包......

非常感谢...

答案 3 :(得分:0)

是的,如果你想在你的应用程序中使用运行时包,你必须使用运行时包来构建它,然后它需要它们(与它们静态链接)。

问题的解决方案取决于实际问题(目前尚不清楚)。

答案 4 :(得分:0)

哦,伟大的疏忽/疏忽(我的) 使用您发布的代码,进行简单的更改测试(使用PChar)。

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

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

定义函数的sitaxis时也一样:

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

测试并说出结果。

的问候。