AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Dyn Array of Record aus DLL

Ein Thema von gmc616 · begonnen am 22. Nov 2006 · letzter Beitrag vom 24. Nov 2006
Antwort Antwort
gmc616

Registriert seit: 25. Jun 2004
Ort: Jena
627 Beiträge
 
Delphi 10.3 Rio
 
#1

Dyn Array of Record aus DLL

  Alt 22. Nov 2006, 16:33
Hallo DPler,

ich möchte ein Record in einer DLL füllen. Dazu habe ich in einer separaten Unit, die sowohl vom Hauptprogramm als auch der DLL verwendet wird, das Record definiert. z.B. so:
Delphi-Quellcode:
unit MyRecords;
...
type TSimpleRecord = record
  Zeile1 : String;
  Zeile2 : String;
end;

type TPSimpleRecord = ^TSimpleRecord;

var
  MyRecord : TSimpleRecord;
  MyPointer : TPSimpleRecord;
Das ich ohne Speichermanager arbeiten will, reicht es der Dll-Funktion einen Zeiger auf das Record zugeben.
Das Hauptprogramm:
Delphi-Quellcode:
unit AppMain;
...
procedure FillRecord (APointer:TPSimpleRecord); stdcall; external 'MyDll.dll';
...
MyPointer := @MyRecord;
FillRecord (MyPointer);
ShowMessage (MyRecord.Zeile1);
Die DLL:
Delphi-Quellcode:
library MyDll;
...
procedure FillRecord (APointer : TPSimpleRecord); stdcall;
begin
  APointer^.Zeile1 := 'erste Zeile';
  APointer^.Zeile2 := 'zweite Zeile';
end;
Ich hoffe der Code ist soweit korrekt. Funktionieren tut er jedefalls.

Nun habe ich aber das Problem, das mein Record weitere Array of Record enthalten muß. z.B. so:
Delphi-Quellcode:
unit MyRecords;
...
type TSimpleRecord = record
  Zeile1 : String;
  Zeile2 : String;
end;

type TDynRecord = record
  Name : string;
  Zeilen : array of TSimpleRecord;
end;

type TPDynRecord = ^TDynRecord;

var
  MyDynRecord : TDynRecord;
  MyDynPointer : TPDynRecord;
Füllen des Record wollte ich ähnlich machen w.o.:
Delphi-Quellcode:
Unit AppMain;
...
procedure FillDynRecord (APointer:TPDynRecord); stdcall; external 'MyDll.dll';
...
MyDynPointer := @MyDynRecord;
FillRecord (MyDynPointer);
Die Funktion in der DLL sieht dann z.B. so aus:
Delphi-Quellcode:
library MyDll;
...
procedure FillDynRecord (APointer : TPDynRecord); stdcall;
begin
  APointer^.Name := 'Test';
  Setlength(APointer^.Zeilen,2);
  APointer^.Zeilen[0].Zeile1 := 'erste Zeile';
  APointer^.Zeilen[0].Zeile2 := 'zweite Zeile';
  APointer^.Zeilen[1].Zeile1 := 'dritte Zeile';
  APointer^.Zeilen[1].Zeile2 := 'vierte Zeile';
end;
Das Füllen des DynRecords in der DLL funktioniert.

Wenn allerdings die Anwendung wieder zurück ins HauptProgramm springt, ist dort mein DynRecord "nicht verfügbar" und bei Rücksprung aus der Function, die FillDynRecord gerufen hat, stürzt die Anwendung mit einer Schutzverletzung beim Speicherzugriff an Adresse xy ab.

Ich vermute, das beim Vergrößern des Array of Record mit setlength() irgendwas im Speicher überschrieben wird.

Was muss ich tun, damit das Dynamische Array of Record korrekt zurück gegeben wird?

Danke vorab schon mal für eure Hilfe.
gmc
  Mit Zitat antworten Zitat
gmc616

Registriert seit: 25. Jun 2004
Ort: Jena
627 Beiträge
 
Delphi 10.3 Rio
 
#2

Re: Dyn Array of Record aus DLL

  Alt 23. Nov 2006, 17:26
Kann mir keiner Helfen??

Ich habe heute festgestellt, dass das Problem nur mit dynamisch geladenen DLL's besteht.
Ich übergebe den Pointer des Records in die DLL und die Dll füllt das Record korrekt.
Erst wenn ich die Dll im Hauptprogramm aus dem Speicher mit FreeLibrary entlade ist mein Record zerstört bzw. nicht verfügbar.

Wieso?
Das Record gehört doch der Hauptanwendung und die DLL bekommt nur einen Zeiger darauf?

das ist mir zu hoch
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#3

Re: Dyn Array of Record aus DLL

  Alt 23. Nov 2006, 18:58
Du Arbeitest mit Delphi-Strings. Da brauchst du den Speichermanager sonst krachst.
Du könntest aber mit PChar arbeiten dann dürfte das Problem gelößt sein wenn du korrekt den Speicher für diese Strings von Windows holst und nicht über den Delphi-MM. Oder du nimmst z.B. Zeile1 : array[0..10000] of char ist aber 'ne gewaltige Speicherverschwendung.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
gmc616

Registriert seit: 25. Jun 2004
Ort: Jena
627 Beiträge
 
Delphi 10.3 Rio
 
#4

Re: Dyn Array of Record aus DLL

  Alt 24. Nov 2006, 14:17
Hmmm ... pchar also. Den Typ verwende ich sonst auch für die Übergabe von Strings in DLLs.
Eine Speichermanager will/kann/darf ich nicht verwenden, da meine Anwendung mit einer weiteren DLL arbeitet, die sich mit dem Delphi-Speichermanager nicht verträgt (laut Dokumentation, und tut sie auch nicht).

Was passiert eigentlich im Speicher wenn ich der Delphi-DLL
a) einen String,
b) ein PChar,
c) einen Zeiger auf einen String übergebe ??

gibt es da irgendwo etwas zum nachlesen?

Ich habe aus dem DynRecord mal ein Object ( = class (TObject) ) gemacht und ebenfalls den Zeiger in die DLL gegeben.
Das gleiche. Nach FreeLibrary ist das Object zerstört.

Ich dachte bis jetzt, dass bei der "normalen" Übergabe von Variablen eine Kopie im Speicher stellt mit der dann (im meinem Fall die DLL) weiter gearbeitet wird. Da die Übergabe von Delphi-Strings in eine DLL ohne Speichermanager nicht funktioniert, dachte ich mir, ich zeige der DLL wo die Daten stehen indem ich nur einen Pointer rüber reiche.
So gebe ich der DLL quasi nur eine Zahl, die Daten stehen im Adressbereich der Hauptanwendung und ich kann auf den Speichermanager verzichten.

Naja, freilich das klapp solange wie sich die Größe der Daten nicht ändert ...
Das scheint wohl mein Denkfehler zu sein. Aber wie denkt man es richtig?

Ich werde erst mal die Strings in PChar ändern. Mal sehen ob das klappt.
Wie holt man Speicher für diese "Strings" korrekt?
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#5

Re: Dyn Array of Record aus DLL

  Alt 24. Nov 2006, 20:41
Zitat von gmc616:
... Eine Speichermanager will/kann/darf ich nicht verwenden, da meine Anwendung mit einer weiteren DLL arbeitet, die sich mit dem Delphi-Speichermanager nicht verträgt
Wenn du irgendwo mit Delphi-Strings arbeitest benötigst Du aber einen.
Hast Du schon mal probiert ob du mit FastMM arbeiten könntest?

Zitat von gmc616:
Was passiert eigentlich im Speicher wenn ich der Delphi-DLL
a) einen String,
b) ein PChar,
c) einen Zeiger auf einen String übergebe ??
zu a, Solange du den String in der DLL nicht veränderst bzw irgendwo anderst hin kopierst: Gar nichts. Wenn Du ihn aber weiter referenzierst kracht es da dann die Referenzzählerei von Exe und DLL durcheimander kommen. Fall C ist praktisch wie Fall b solange du den String nicht verändern darfst (Deshalb steht oft in der VCL bei Aufrufen in die Win32-API PChar(MeinDelphiString). Fall b heißt du mußt dann mit den nicht gerade schönen Funktionen für PChar arbeiten.

Zitat von gmc616:
Ich habe aus dem DynRecord mal ein Object ( = class (TObject) ) gemacht und ebenfalls den Zeiger in die DLL gegeben.
Das gleiche. Nach FreeLibrary ist das Object zerstört.
Ohne gemeinsamen Memory-Manager: Russisches Roulette.

Zitat von gmc616:
Ich dachte bis jetzt, dass bei der "normalen" Übergabe von Variablen eine Kopie im Speicher stellt mit der dann (im meinem Fall die DLL) weiter gearbeitet wird. Da die Übergabe von Delphi-Strings in eine DLL ohne Speichermanager nicht funktioniert, dachte ich mir, ich zeige der DLL wo die Daten stehen indem ich nur einen Pointer rüber reiche.
So gebe ich der DLL quasi nur eine Zahl, die Daten stehen im Adressbereich der Hauptanwendung und ich kann auf den Speichermanager verzichten.
Dies gilt nur für skalare Typen wie Boolean, Int, Float. Für Objekte und den Sondertyp (Delphi-String) gelten gesonderet Regeln (Objekte wird nur die Referenz übergeben und der Delphi-Ansi-String verwendet Refernzzählung.

Zitat von gmc616:
Naja, freilich das klapp solange wie sich die Größe der Daten nicht ändert ...
Das scheint wohl mein Denkfehler zu sein. Aber wie denkt man es richtig?

Ich werde erst mal die Strings in PChar ändern. Mal sehen ob das klappt.
Wie holt man Speicher für diese "Strings" korrekt?
Ohne Memorymanager darfst Du nur mit C-Kompatiblen-Typen arbeiten. "Strings" (PChars) reservierst du mit StrAlloc (müßte es aus der Hüfte geschossen sein).
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:17 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