我创建了一个包,我想使用我的包的 BPL 文件...
我的包有 VCL.dcp 和 RTL.dcp 作为必需的库,我在我的应用程序中加载这个包没有任何错误,但是当我想卸载它时,显示访问冲突!
如果我使用运行时包(“vcl”和“rtl”)构建我的应用程序,则不会显示访问冲突!
这是什么意思 ?!我的应用程序需要 VCL 和 RTL 库来加载 BPL?!我想像 DLL 文件一样加载我的包,有什么解决方案吗?
我正在使用德尔福 2010
多谢 ...
我创建了一个包,我想使用我的包的 BPL 文件...
我的包有 VCL.dcp 和 RTL.dcp 作为必需的库,我在我的应用程序中加载这个包没有任何错误,但是当我想卸载它时,显示访问冲突!
如果我使用运行时包(“vcl”和“rtl”)构建我的应用程序,则不会显示访问冲突!
这是什么意思 ?!我的应用程序需要 VCL 和 RTL 库来加载 BPL?!我想像 DLL 文件一样加载我的包,有什么解决方案吗?
我正在使用德尔福 2010
多谢 ...
您的 BPL 需要 RTL 和 VCL 包。如果您的应用程序不需要它们,那么这意味着 RTL 和 VCL 单元被编译到您的 EXE 文件中。当您的 EXE 加载 BPL 时,您现在拥有RTL 和 VCL 单元的两个副本— 一组副本来自 EXE 内部,第二个副本来自您的包隐式导致加载的 RTL 和 VCL 包。
Delphi 并不打算适应这种情况。您的内存可能由一个 RTL 分配并试图由另一个 RTL 释放。或者,EXE 中可能存在引用 VCL 包中的函数的函数指针。
我为您看到了三个选项:
编译您的 EXE 以使用包。具体来说,它应该需要您的 BPL 所需的相同 RTL 和 VCL 包。
使您的 BPL不需要任何其他包。如果它不需要 RTL 和 VCL,那么您的包使用的任何 RTL 和 VCL 单元都将被编译到您的 BPL 中。您最终将再次获得两个单独的副本,但它应该会更好地工作,因为两个副本都不会认为它应该被共享。
像一个真正的 DLL 而不是像一个包一样加载你的包。你说你想像 DLL 一样使用它,那么就这样做吧。使用LoadLibrary
, 然后使用GetProcAddress
来获取您想要调用的任何函数。如果你走这条路,最好不要让你的代码成为一个包。将其设为 DLL,并导出仅使用您希望在其他 DLL 中找到的参数类型的函数,例如整数、字符指针和记录指针,而不是字符串或对象。
应该清楚,第一个选项是最简单的。第二个可能会起作用,听起来这是您更喜欢的方式,但我预计它会在最终起作用之前产生更多的头痛。如果您在该项目的生命周期内必须使用其他开发环境,则第三种选择是最好的。
你的包裹里面有什么?
你用它做什么工作?
你如何充电和放电?这里面是什么?
在卸载之前你会如何处理包裹?
当您卸载它时,您使用的所有对象/表单/组件/...都被释放?
添加:我认为您在尝试 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] 已卸载
问候。
感谢您的帮助...
我在这里放了一个我的包和我的应用程序的例子来查找问题所在!
我们有一个包,不需要像 VCL 和 RTL 这样的运行时包,换句话说,我从包的 Requires 部分中删除了所有库:
我的包裹包含一个带有以下代码的表格:
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 Shows!
@Neftalí:如果我只是加载和卸载包,没有 AV 节目,但我认为这是因为我不调用某些例程或对象,或者......如果我使用对象和函数,它们需要 VCL 或 RTL 库还有……这个包,用完后我会得到一个AV……是真的吗?!
如果我使用运行时包(VCL 和 RTL)构建我的应用程序,则不会显示任何 AV!
我很困惑!,我想使用不需要任何运行时包的 BPL 包...
多谢 ...
是的,如果你想在你的应用程序中使用运行时包,你必须用运行时包构建它,然后它需要它们(与它们静态链接)。
您的问题的解决方案取决于问题的实际情况(目前尚不清楚)。
Ohhhhh,很大的疏忽/忽视(我的)。
使用您发布的代码,对其进行简单的更改测试(使用 PChar)。
function ShowForm(FCaption, LCaption : String) : PChar;
...
Result := PChar(F.MyEdit.Text);
...
定义函数的坐标轴时也是如此:
ShowF : function(FCaption, LCaption : String):PChar;
测试它并说出结果。
问候。