#delphi #dll
#delphi #dll
Вопрос:
Я пытаюсь создать модульное приложение на delphi2010, используя BTL. Проблема в том, что когда я пытаюсь создать класс в БПЛ, я получаю это сообщение об ошибке.
Я не выполнял никаких операций с ресурсом (файлом RES)!
Procedure TControllerMain.Btn1OnClick(Sender: TObject);
type
TInitProcedure = function: TModuleBaseClass; stdcall;
TModuleBaseClass= class of TModuleBase;
var
h: HMODULE;
proc: TInitProcedure;
vClass: TModuleBaseClass;
begin
h := LoadPackage('test.bpl');
@proc := GetProcAddress(h, 'InitializePlugin');
vClass := proc();
vClass.Create(nil); // error here
UnloadPackage(h);
end;
dll-код
TModuleBase — это TCustomPanel
type
TVLCVideo = class(TModuleBase)
private
...
public
...
end;
function InitializePlugin: TModuleBaseClass; stdcall;
implementation
function InitializePlugin: TModuleBaseClass;
begin
Result := TVLCVideo;
end;
exports
InitializePlugin;
end.
Комментарии:
1. Такого рода ошибки возникали бы во время потоковой передачи DFM, но только в том случае,
TModuleBase
если бы они были получены изTForm
,TFrame
илиTDataModule
, не изTCustomPanel
.2. Хорошо, можете ли вы сказать мне, есть ли какой-либо способ использования компонентов в dll? Я не хочу создавать ActiveX-компонент
3. Возникает ли у вас такая же проблема, если
InitializePlugin()
возвращает созданный объект вместо типа класса? Как выглядит стек вызовов при возникновении ошибки?4. Спасибо, Реми, я решил проблему, используя интерфейсы with
5. @relative, не могли бы вы вставить решение в качестве ответа и принять его самостоятельно, пожалуйста? Это может помочь будущим посетителям с той же проблемой.
Ответ №1:
Решение :
Я использовал TCustomPanel для предка TModulBase, но я увидел проблему, Реми прав. и для них я удаляю класс-предок для замены на интерфейс, и все мои другие плагины должны использовать тот же интерфейс (если вы используете этот способ с обычным проектом dll, вы получите другую ошибку! Я пытался: (вы должны использовать его с бпл (бпл — это тоже dll))
PIModuleBase = ^IModulBase;
IModulBase = interface
...
end;
это нажатие кнопки — просто пример, который вам нужно создать для класса modul manager
Procedure TControllerMain.Btn1OnClick(Sender: TObject);
type
TInitProcedure = function: PIModuleBase; stdcall;
var
h: HMODULE;
proc: TInitProcedure;
vClass: PIModuleBase;
begin
h := LoadPackage('test.bpl');
@proc := GetProcAddress(h, 'InitializePlugin');
vClass := proc();
vClass^.setParent(form1);
vClass^.setPosition(0,0,100,100);
vClass^.play(PChar('url of media'));
//UnloadPackage(h);
end;
type
TVLCVideo = class(TCustomPanel, IModulBase)
private
...
public
...
end;
function InitializePlugin: PIModuleBase; stdcall;
implementation
function InitializePlugin: PIModuleBase;
var
v : TVLCVideo;
begin
v := TVLCVideo.Create(nil);
Result := IModuleBase(v);
end;
exports
InitializePlugin;
end.
Важные вещи :
Вы не можете импортировать файл библиотеки интерфейса в файл пакета модуля напрямую или в основной проект приложения! вам нужно создать новый проект btl только для файлов интерфейса и общей библиотеки, и для них вам нужно поместить ваши пакеты модулей в раздел requires, например, как vlc, rtl.
И вам нужно создать основное приложение с этим пакетом интерфейса