我创建了一个包,我想使用我的包的BPL文件...
我的软件包将VCL.dcp和RTL.dcp作为必需的库,我在我的应用程序中加载此软件包时没有任何错误,但是当我想卸载它时,显示了访问冲突!
如果我使用运行时软件包构建我的应用程序(“vcl”和“rtl”),则不显示访问冲突!
这是什么意思?!我的应用程序需要VCL和RTL库来加载BPL吗?我想像DLL文件一样加载我的包,有什么解决方案吗?
我正在使用Delphi 2010
非常感谢...
答案 0 :(得分:8)
您的BPL需要RTL和VCL套餐。如果您的应用程序不需要它们,则表示RTL和VCL单元已编译到您的EXE文件中。当您的EXE加载BPL时,您现在有两份的RTL和VCL单元 - 一组副本来自EXE,第二份副本来自您的包的RTL和VCL包隐含地导致被加载。
德尔福无意适应这种情况。您可能拥有一个RTL分配的内存,并试图被其他RTL释放。或者,EXE中可能存在引用VCL包中的函数的函数指针。
我为您看到三个选项:
编译您的EXE以使用包。具体来说,它应该需要您的BPL所需的相同RTL和VCL包。
让您的BPL 不需要任何其他套餐。如果它不需要RTL和VCL,那么您的包使用的任何RTL和VCL单元都将被编译到您的BPL中。您最终会再次使用两个单独的副本,但它应该更好用,因为两个副本都不会认为它应该被共享。
像真正的DLL一样加载您的包,而不是像包一样。你说你想像DLL一样使用它,所以这样做。使用LoadLibrary
,然后使用GetProcAddress
获取您要调用的任何函数。如果你走这条路,最好不要让你的代码成为一个包。使它成为DLL,并导出仅使用您希望在其他DLL中找到的参数类型的函数,如整数,字符指针和记录指针,而不是字符串或对象。
应该很清楚,第一个选项是最简单的。第二个可能会起作用,听起来就像你喜欢的那样,但我预计它会在它最终起作用之前产生更多的麻烦。如果您在此项目的生命周期内必须使用其他开发环境,则第三种选择最佳。
答案 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部分删除了所有库:
我的包中包含一个包含以下代码的表单:
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;
测试并说出结果。
的问候。