Delphi: ошибка «Ресурс не найден»?

#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.

И вам нужно создать основное приложение с этим пакетом интерфейса

Сборка с использованием пакетов среды выполнения

введите описание изображения здесь