Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung (https://www.delphipraxis.net/210416-dll-erstelt-mit-d10-4-community-aufruf-d2006-zugriffsverletzung.html)

Michael Habbe 21. Apr 2022 12:09

DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung
 
Hallo zusammen.

In diesem Thread (https://www.delphipraxis.net/203147-...er-delphi.html) hat Redeemer eine superkompakte Klasse für die Erstellung von QR-Codes erstellt.

Die wollte ich nach einem Test mit Delphi 10.4 Community nach Turbo Delphi portieren, stieß da aber auf einige Probleme u.a. bzgl. pngimage (was ich mit etwas Aufwand beheben konnte). Aber nach delphi 2006 sind zu viele Änderungen erfolgt.

Nach einigen Versuchen habe ich mir dann überlegt, eine DLL mit D10.4C zu erstellen, um sie dann in Delphi 2006 zu laden und den QR-Code per Bitmap zu übertragen.

Die DLL mit Delphi 10.4 Community:
Delphi-Quellcode:
library GiroCode;

uses
//  ShareMem,
  System.SysUtils,
  System.Classes,
  Graphics, ExtCtrls,
  RedeemerQR in '..\..\..\BorlandDelphiKomponenten\RedeemerQR\RedeemerQR.pas',
  RedeemerInheritablePNG in '..\..\..\BorlandDelphiKomponenten\RedeemerQR\RedeemerInheritablePNG.pas';

{$R *.res}

type
  TTextGiroCode = array [1..12] of ShortString;

function GenerateCode(GC: TTextGiroCode; var QRbmp: TBitmap): Integer;
var
  QR: TRedeemerQR;
  GC_Text: String;
  i: Integer;
begin
  result := 0;
  GC_Text := '';
  for i := 1 to 11 do
    GC_Text := GC_Text + GC[i] + #13;
  GC_Text := GC_Text + GC[12];

  QR := TRedeemerQR.Create();
  try
    QR.LoadFromString(AnsiString(GC_Text), ecMedium);

// hier kommt es zur Zugriffsverletzung
    QRbmp.Width := QR.Width + 2;
// auch, wenn Height vor Width steht
    QRbmp.Height := QR.Height + 2;

    QRbmp.Canvas.Draw(1,1, QR);
    result := 1;
  finally
    QR.Free;
  end;
end;

exports
  GenerateCode index 1;

begin
end.

Der Aufruf aus Delphi 2006 (in D10.4C sieht die Unit genauso aus):
Delphi-Quellcode:
[...]
type
  TTextGiroCode = array [1..12] of ShortString;

{$R *.dfm}

procedure TForm1.Button3Click(Sender: TObject);
var
  FuncCall: function(GC: TTextGiroCode; var QRbmp: TBitmap): Integer;
  DllHandle: THandle;
  text: TTextGiroCode;
  i: Integer;
  bmp: TBitmap;
begin
  DllHandle := loadlibrary('GiroCode.dll');
  if DllHandle = 0 then
  begin
    ShowMessage('DLL-Ladefehler: GiroCode.dll nicht gefunden!');
    Exit;
  end;

  @FuncCall := getprocaddress(DllHandle, 'GenerateCode');
  if (@FuncCall = Nil) then
    ShowMessage('GetProcAddress-Fehler: GiroCode.dll enthält keine Function "GenerateCode"')
  else
  begin
    for i := 1 to 12 do
      text[i] := Memo1.Lines[i-1];
    bmp := TBitmap.Create;
    bmp.Width := 0;
    bmp.Height := 0;
    FuncCall(text, bmp);
    image1.Picture.Assign(bmp);
    //bmp.SaveToFile('qr.png');
  end;
  FreeLibrary(DLLHandle);
end;
Bei Aufruf der DLL aus D10.4C ist alles in Ordnung und der QR-Code wird angezeigt.
Wenn nun die DLL aus Delphi2006 aufgerufen wird, kommt es inzu einer Zugriffsverletzung an der Stelle, wo QRbmp.Width zugewiesen wird. Eine Auswertung der Variablen ergibt, dass diverse Eigenschaften nicht verfügbar sind.
Kann mir jemand helfen und verraten, wo mein Fehler liegt??? :(

PS: Die Verwendung von "sharemem" oder nicht bringt keinen Unterschied.

Danke
Michael

Uwe Raabe 21. Apr 2022 12:45

AW: DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung
 
Das Problem wird sein, dass die DLL eine TBitmap gemäß der Deklaration in Delphi 10.4 erwartet, dein Programm aber eine TBitmap gemäß der Deklaration in Delphi 2006 liefert.

himitsu 21. Apr 2022 13:31

AW: DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung
 
Nicht nur, dass das TBitmap anders aufgebaut sein kann (unterschedliche Delphi-versionen), die DLL verwendet auch ihren eigenen Speichermanager und ihre eigenen globalen Instanzen (Font/Brush/Pen/...), was auf der anderen Seite garnicht funktioniert kann.

Du könntest maximal ein MSDN-Library durchsuchenHBITMAP verwenden, wo dann die WinAPI den gemeinsamen Grundstock bereitstellt.
Oder nur den Inhalt (Pixelspeicher) des Bitmaps übergeben/kopieren.

Michael Habbe 21. Apr 2022 14:26

AW: DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung
 
Alles klar. Danke erstmal.

Überlege gerade, die Größe in Width und Height sowie die Pixels als Array zu übertragen.

Melde mich wieder....

Danke
Michael

hoika 21. Apr 2022 16:06

AW: DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung
 
Hallo,
ich würde der Dll einen Dateinamen mit übergeben,
wohin die Dll das Bitmap speichern soll.

himitsu 21. Apr 2022 16:56

AW: DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung
 
Also im Prinzip darfst du keine Objekte übergeben,
aber du kannst den Objekten ein Interface verpassen und das übergeben.

Selbst wenn die Objekte intern gleich wären,
alleine TObjekt (die Grundklasse für ALLES) ist zwischen 2006 und 10.4 schon in großen Teilen verändert.

Und auch Strings und teilweise die dymaischen Arrays wurden 2009 grundlegend umgebaut. (funktionell wurde nachher zwar wieder einiges Rückgebaut, aber strukturell immernoch unterschiedlich)


Aber selbst z.B. Delphi 2006 und 2007, welche nicht nur fast überall "identische" Klatten, sondern sogar den selben Compiler hatten und somit praktisch nahezu 100% kompatibel sind,
da sind TItgendwas der EXE und TIrgendwas der DLL komplett unterschiedlich, da jeder seine eigene RTTI hat, dazu kommt dann noch der jeweil eigene Speichermanager (den Teil könnte man über ShareMem umgehen) und eben auch jeder eigene Variablen für globale Objekte.
Hier also von den verwendeten globalen Font/Pen/Brush jeder seine eigene Instanz.






Oder hier eben das interne HBITMAP übergeben und drüben direkt damit arbeiten, bzw. einem anderen TBitmap dieses HBITMAP unterschieben, so dass beide Seiten mit dem Selben arbeiten.

Bei TStream gäbe es z.B. ein IStream im Windows, was aber leider nicht mit dem TStream von Delphi kompatibel ist, womit man TStream nicht direkt als IStream weitergeben kann, sondern erst umkopieren muß.
Oder eben den Speicher der Pixel oder die Bytes des Stream (SaveToStream) als Buffer übergeben und drüben wieder in ein anderes TBitmap einlesen.

ol1uw 21. Apr 2022 17:53

AW: DLL erstelt mit D10.4 Community, Aufruf in D2006 Zugriffsverletzung
 
Hallo

wenn es nicht primär darum geht genau diese Komponente in einer DLL zu verwenden.
Es gibt ja durchaus alternativen z.B. DelphiZXingQRCodeEx.

Uwe


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:36 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz