Einzelnen Beitrag anzeigen

Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.366 Beiträge
 
Delphi 10.3 Rio
 
#1

bpl einbinden über Interface

  Alt 10. Mai 2017, 09:30
Delphi-Version: 7
Hallo,
ich habe hier ein Delphi 7 Projekt, das nicht so schnell und einfach auf eine höhere Delphi-Version umgestellt werden kann (wobei wir dran arbeiten). Es gibt einen Funktionsbereich, der allerdings nicht sauber funktioniert und ich den gerne mit einer höheren Delphi-Version umsetzen würde, weil der Bereich damit problemlos geht.

Dazu habe ich 2 Optionen:
1. eigenständiges Programm
2. DLL / BPL

Da ich Daten zwischen den Bereichen austauschen muss, fällt 1 schon mal fast weg, obwohl über MemoryMappedFiles sicherlich Möglichkeiten da wären unstrukturierte Daten auszutauschen.

//Edit:
So Dinge wie Kommunikation über Http (sprich das externe Programm hat nen http-Server eingebaut mit dem ich dann kommuniziere) sowie COM fallen weg, da das ganze dann auch bei Kunden laufen muss, ohne dass ich ständig hinter her renne um lokal irgend welche seltsamen Firewall oder Systemkonfigurationen zu korrigieren //Edit

DLL: würde schon mehr Möglichkeiten bieten, brauch aber den Speichermanager von Borland.

BPL: da habe ich die Möglichkeit über Interfaces doch einfacher Dinge auszutauschen. Allerdings kenne ich da die Beispiele nur, wenn die "Hauptanwendung" und die bpl mit der selben Delphi-Version geschrieben sind.

Mal eben flux ein Beispiel aufgesetzt:

Interface:

Delphi-Quellcode:
type
  ITest = Interface
  ['{4BED69D1-E83F-4F85-8DA3-7E2F199F427C}']
    function GetName: Ansistring;
    procedure Test2(const AValue: AnsiString);

    property Name: AnsiString read GetName;
  end;
Das wird im Projekt XE4 in einer BPL abgebildet und implementiert

Delphi-Quellcode:
type
  TFoo = class(TInterfacedObject, ITest)
    FName: Ansistring;
  public
    function GetName: Ansistring;
    procedure Test2(const AValue: Ansistring);
  end;

implementation

{ TFoo }

function TFoo.GetName: Ansistring;
begin
  result := FName;
end;

procedure TFoo.Test2(const AValue: Ansistring);
begin
  FName := 'Hallo ' + AValue;
end;

und schließlich exportiert:

Delphi-Quellcode:
function InitFoo: ITest;


exports
   InitFoo;

implementation

uses Impl;

function InitFoo: ITest;
begin
  result := TFoo.Create;
end;

In Delphi 7 im "Hauptprogramm" dann dynamisch eingebunden:

Delphi-Quellcode:
type
  TInitProc = function (): ITest;

procedure TForm1.LoadBPL;
var
  createI: TInitProc;
begin
  FBplHandle := LoadPackage(PChar('x:\foo\PackageProj.bpl'));
  if FBplHandle <> 0 then begin
    createI := GetProcAddress(FBplHandle, 'InitFoo');
    FTest := createI();
  end
  else
  begin
    raise Exception.Create('BPL konnte nicht geladen werden.');
  end;
end;

und ich kann anschließend mit dem Interface arbeiten, d.h. Strings übergeben und auch Strings abrufen. Und das alles mit unterschiedlichen Delphi-Versionen und ohne böse Fehlermeldung. Ich war doch sehr überrascht wie schmerzlos das ganze geht.

Nun endlich die Fragen:
1. Warum brauche ich hier keinen extra Verweis auf den Speichermanager von Borland, der bei DLLs und Strings quasi Pflicht ist? Steckt der in der bpl schon grundsätzlich drin?
2. Wenn das Beispiel komplexer wird und ich in der bpl weitere Delphipackages (rtl, Soap) benötige, machen die mir ggf. dann irgend wann Probleme, weil im Hauptprogramm Packages/Units mit den selben Namen schon vorhanden sind?
3. Gibt es irgend etwas das ich in meiner Euphorie übersehe?

Grüße
  Mit Zitat antworten Zitat