![]() |
Dynamisches Array in DLL kann nicht erweitert werden
Hallo,
ich habe in meinem DLL-Code eine Prozedur, die ein dynamisches Array zurückliefern soll. Die Prozedur beginnt mit:
Delphi-Quellcode:
und SingleDataSet ist deklariert als:
procedure GetValues(Config : ConfigRec; var Ergebnis : Array of SingleDataSet);
Delphi-Quellcode:
Das kompiliert auf den ersten Blick fehlerfrei durch.
type SingleDataSet = packed record
DataSetNr : Byte; DataSetName : string[30]; DataSetValue : Integer; SavingTime : TDateTime; end; Wenn ich allerdings in der selben Prozedur das Array erweitern möchte, um Daten anzufügen, scheitert dies:
Delphi-Quellcode:
mit Fehler E2008 Inkompatible Typen. Wie kann ich das trotzdem bewerkstelligen in Verbindung mit einem dynamischen Array?
SetLength(Ergebnis, 2);
|
AW: Dynamisches Array in DLL kann nicht erweitert werden
Standardmässig benutzen Programm und Dll verschiedene Speichermanager.
Das bedeutet das in einer DLL Schnittstelle nur einfache typen wie integer, double, Pchar, etc verwendet werden sollten. Du kannst die Unit Sharemem mit einbinden. Funktioniert aber nur wenn die DLL und das Programm mit Delphi kompiliert werden. Das nächste Problem: die Deklaration von
Delphi-Quellcode:
Das ist ein OpenArray.
var Ergebnis : Array of SingleDataSet
![]() Am besten Du deklarierst einen Typ für das Array:
Delphi-Quellcode:
Ich wäre aber sehr vorsichtig mit solchen Parametern über eine Dll.
type tSingleDatasetArray = Array of SingleDataSet;
Am besten stelle auf packages um. (dafür sind diese gedacht). Da die Dll ja sowieso Delphi Only ist mit solchen Parameter würde ich diesen Weg gehen. |
AW: Dynamisches Array in DLL kann nicht erweitert werden
Array of SingleDataSet ist ein OpenArray-Parameter, kein dynamisches Feld.
Richtig geht es so:
Delphi-Quellcode:
TSingleDataSetArray = Array of SingleDataSet;
procedure GetValues(var Ergebnis:TSingleDataSetArray); |
AW: Dynamisches Array in DLL kann nicht erweitert werden
Ich würde die Länge des Arrays auch schon vor dem Aufruf setzen. Da es sich hier ja um einen Referenzparameter handelt, könntest du dir noch eine zusätzliche Funktion bauen, die dir die benötigte Länge zurückgibt.
Sowas in der Art:
Delphi-Quellcode:
So habe ich es in meinen DLLs aufgebaut und das funktioniert wunderbar. Erinnert in abgewandelter Form auch an die Win32API bei der das ähnlich gelöst wird. Erst die Methode mit dem Referenzparamenter nil aufrufen um sich die benötigte Länge zu holen, dann die Länge des Arrays setzen und dann die Methode mit dem richtigen Array Parameter wieder ausführen.
procedure SomeMethod;
var Count: Integer; MyArray: TSingleDataSetArray; begin if MyDllInstance.GetElementCount(Count) then begin SetLength(MyArray, Count); GetValues(MyArray); end; end; |
AW: Dynamisches Array in DLL kann nicht erweitert werden
Zitat:
Delphi-Quellcode:
leider mit dem gleichen Ergebnis. Innerhalb der Prozedur mache ich noch nichtmal was mit dem "Ergebnis", weder Größenanpassungen noch sonst was. Aber es wird leider jedesmal mit der Exception quittert.
type TIntegerArray = Array of integer;
... procedure GetValues(Config : ConfigRec; var Ergebnis : TIntegerArray); ... |
AW: Dynamisches Array in DLL kann nicht erweitert werden
Hallo,
hast du denn ShareMem eingebunden? |
AW: Dynamisches Array in DLL kann nicht erweitert werden
Oder der Methode noch die Direktive
Delphi-Quellcode:
mitgeben. Das sollte dann auch funktionieren.
stdcall;
|
AW: Dynamisches Array in DLL kann nicht erweitert werden
Zitat:
Das beeinflusst in keiner Weise das Speichermanagement, sondern nur wie übergebene Parameter auf dem Stack behandelt werden beim verlassen der Routine. Das hat nichts mit dem allozieren von Speicher zu tun. Ohne Sharemem wird das nicht funktionieren. Damit dynamische Arrays und auch Strings mit Dll's funktionieren muss der gleiche Speichermanager benutzt werden |
AW: Dynamisches Array in DLL kann nicht erweitert werden
Nachdem ich nun alle Vorschläge ausprobiert habe und Packages ausscheiden, half mir die Direktive:
Delphi-Quellcode:
stdcall;
innerhalb der DLL, und nun wird der OpenArray-Parameter korrekt in beide Richtungen übergeben. ShareMem hatte ich auch versucht, allerdings gelang es auch ohne und soweit ich das verstanden habe, macht es nur Sinn, wenn die Applikation, welche später auf die DLL zugreift, auch eine Delphi-Applikation ist - was bei mir aber definitiv nicht der Fall ist. |
AW: Dynamisches Array in DLL kann nicht erweitert werden
Damit hast du den Fehler nicht beseitigt, nur das Symptom Zugriffsverletzung tritt zufällig an dieser Stelle nicht mehr auf. Wenn Speichermanager A Speicher freigibt, den Speichermanager B reserviert hat, wird Speichermanager B irgendwann versuchen darauf zuzugreifen. Das kann in einem völlig anderen Programmteil irgendwann wieder zur Zugriffsverletzung führen und du wirst nicht wissen warum.
|
AW: Dynamisches Array in DLL kann nicht erweitert werden
Da hat Blup eindeutig recht.
Zitat:
|
AW: Dynamisches Array in DLL kann nicht erweitert werden
Ja das dachte ich mir schon, und bin auch fündig geworden. Es sind die Strings im Packed-Record des offenen Arrays, die Probleme machen. Wenn ich diese entferne, kann ich das Array beliebig erweitern und es tritt keinerlei Absturz auf.
Dass man Strings nicht verwenden sollte als Austausch zwischen DLL und MainApp, habe ich schon öfter gelesen. Aber gleichzeitig las ich etwas von Ansichar. Wäre denn folgende String-Alternative besser geeignet?
Delphi-Quellcode:
Oder wirklich komplett verzichten?
type SingleDataSet = packed record
DataSetNr : Byte; DataSetName : Array [0 .. 255] of Ansichar; DataSetValue : Integer; end; |
AW: Dynamisches Array in DLL kann nicht erweitert werden
ShortStrings sind auch "Records"
also ShortString oder String[1] bis String[255] "Einziger" Nachteil ... die gibt es nur als ANSI und mit maximal 255 Zeichen (256 Byte) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:33 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz