![]() |
AW: Delphi 7 DLL-Exports überladener Methoden?
Zitat:
![]() Bis bald... Thomas |
AW: Delphi 7 DLL-Exports überladener Methoden?
Ja (und Anderes), aber liefert nichts verwertbares.
Zitat:
nochmal ... jetzt geht's plötzlich sieht aber genauso aus, wie in den offiziellen Headern. [/edit] Hab grade mal jenen angeschrieben (oder vielleicht seinen Sohn, weil Frederik anstatt Arvid), welcher damals von Hagen quasi die mehreren Gigabyte an Nachlass übernommen hatte. |
AW: Delphi 7 DLL-Exports überladener Methoden?
Mist, dachte schon ich hab den Grund, aber war's leider nicht.
Hatte mir ja eine VM mit Delphi 7 neu aufgesetzt und da drin dann das "falsche" Verzeichnis erwischt. Die Header aus der 5.1c kopiert und mit den DCU der 5.2 versucht zu kompilieren. Aber egal, denn es gibt keinen Unterschied. |
AW: Delphi 7 DLL-Exports überladener Methoden?
So, ich hab erstmal die alte/letzte ZIP des DECMath in ein GitRepo gepackt,
die verschiedenen Verzeichnisse aufgelöst und alles in den Root, mit versionsabhängigen Branches/Tags, und dort nach zeitlichem Verlauf (Änderungsdatum) unter Angabe der originalen Bearbeiter mit rückdatierten Commits, den einen historischen Verlauf gebildet. Der alte Aufbau liegt aktuell noch als erster Versuch im Branch main.old bei. Wenn dann die DLL funktioniert, würde ich sie, inkl. neuer Import-PAS, noch hinzufügen. Und dazu noch ein paar Links/Dokus, zu den wichtigsten Seite/Posts/Threads, bezüglich dieses Themas. ![]() |
AW: Delphi 7 DLL-Exports überladener Methoden?
Also so richtig versteh ich das irgendwie nicht.
Beispiel: NECBuild knallt sogar, wenn man keine Parameter angibt, obwohl diese Funktion eindeutig ist. Komischer Weise knallte sie auch, als ich die Parameterliste dran ließ, aber dann sah ich im Git (erste versuche), dass es doch mal ging, auch mit den Parametern ... wieder rein und nun geht es doch. Dann ging der Export mit
Delphi-Quellcode:
nicht, aber später ging es plötzlich.
name 'xxx'
Ursprünglich hatte ich Eindeutiges nicht umbenannt, aber nun überall einheitlich mindestens den Unitname davor. Ansonsten hab ich jetzt erstmal alle Funktionen als Exporte drin, aber Zuvieles wieder auskommentiert, weil es nicht kompilieren wollte. Aber nun noch rausbekommen, warum so Einiges immernoch einfach nicht will. :wall: Ich mach jetzt nochmal bissl Pause und hab die VM ganz runtergefahren. Aber falls wer Lust hat und schauen möchte, ob er/sie/es was findet ... siehe GitHub. :cyclops: :love: ![]() Branch: DLL DLL-Projekt: \Part_II\DECMath.dpr bzw. GroupDECMath.bpg Delphi7-DCU: \Archive\D7\*.dcu PAS-Header: \Archive\Part_II\LibIntf\*.pas sowie \Archive\Part_II\*.pas [add] Zusammenfassung aller PAS-Headers: \Part_II\DECMath_Headers.txt aus \Archive\Part_II\LibIntf\*.pas Zusammenfassung des DCU-Disassembly: \Part_II\DECMath_Disassemble.txt aus \Archive\D7\*.dcu ohne DefaultParams und sortiert, aber vergleichbar ... braucht noch bissl [/add] [add2] Mist, nach Abgleich sind die Parameter der DCU und Header-PAS praktisch identisch. Bis auf ein nutzloses Overload, aber das sollte egal sein. [/add2] --- Branch: main = letzter/aktueller Stand nach Version+Datum Branch: orginal-zip-content-by-date = alter ZIP-Inhalt nach Datum (Versionen als Unterverzeichnisse) |
[gelöst] Delphi 7 DLL-Exports überladener Methoden?
Ahhhhhhhhhhhh, i werd' irre.
Hab die Gründe raus.
PS: Zitat:
Delphi-Quellcode:
Selbst das kompiliert anstandslos,
exports
NSet(var A: IRational; const N: IInteger; const D: IInteger = nil), NSet(var A: IRational; const N: IInteger; const D: IInteger), NSet(var A: IRational; const N, D: IInteger); auch wenn so drei Mal die selbe Funktion mit dem gleichen Namen exportiert werden und Delphi hier nichmal eine Warnung wirft, dass hier mehrmals der gleiche Name "NSet" in der Exports-Liste steht. |
[gelöst] Delphi 7 DLL-Exports überladener Methoden?
[del]
|
AW: Delphi 7 DLL-Exports überladener Methoden?
I am sorry if missunderstand the context of this thread.
What i got is you need a way to declare and use functions from a library, and prefer to save on jumps (branching) as much as you can for performance. If that is the case then i would suggest to drop the whole Delphi default export/import system and use your own: 1) Make your library have a table of pointers to the needed functions (your exports), it is better of that table is simple global record or an global defined array. 2) DLL on loading will fill that table with the addresses of the functions you need to export, this might be ditched if you can manage to declare that table as constant and the compiler manage to full the addresses automatically. 3) Export one function and one only is enough, GetExportTable. 4) well the rest is easy.. i think you got it out from here, as it is easy as it sound for the import part. See, Delphi compiler generate ugly/slow code for the static imported functions, the calling code will do be like this .dpr.97: MessageBeep(10); 004D882A 6A0A push $0a 004D882C E847A0F3FF call MessageBeep // <-- this a call to the same EXE the called MessageBeep inside the EXE is doing such jump, again !!!!!! :function MessageBeep; external user32 name 'MessageBeep'; 00412878 FF2560344E00 jmp dword ptr [$004e3460] Where the address $004e3460 holds the actual address to MessageBeep the function in user32.dll, and had being resolved by the OS. So two branching per API call, while if you used my suggestion above (or any other way you see fit), you can save on a jmp/branch, relieving the CPU cache, while allowing any sort of naming you might need. |
AW: Delphi 7 DLL-Exports überladener Methoden?
Es ist nicht Delphi, sondern Windows, bzw. das PE-Dateiformat (COFF).
Ja, statische DLL-Importe laufen über eine Import-Tabelle, welche aus vielen JMP+Adresse besteht, wo Delphi erstmal mit einem CALL rein springt und von dort dann erst zum eigentlichen DLL-Export. Und ja, wenn ich diese Adressen selbst verwalte (statt Methoden also MethodenZeiger verwende), könnte ich jeweils den einen JMP weglassen. Aber erstmal ist die Verwendung solcher Interfaces unintuitiver und ich habe eh noch Hoffnung auf bessere Lösungsansätze. * Direkt den originalen Quellcode neu kompilieren. * Oder zumindestens statt der .DCU an .OBJ-Dateien zu gelangen und statt der DLL alles direkt in die EXE zu linken. Zukünftig ist noch geplant die Einzel-Funktionen und Interfaces in Custom-Records zu verpacken. Dann würde ich da eventuell weitere Überlegungen in Betracht ziehen, dort nochmal etwas zu optimieren, bezüglich der JUMP/CALL. Mir ging es erstmal darum zusätzlich noch weitere/eigene JUMP/CALL dort reinzuschieben, und auch dafür noch tausende Wrapper-Funktionen schreiben zu müssen. (das hat sich zum Glück nun erledigt) Prinzipiell kompiliert jetzt erstmal alles, auch wenn ich an einigen Stellen noch rumfummeln muß. (aktuell sind dynamische Arrays und Strings dran) Delphi 7 DLL-Exports : ![]() Delphi 2006+ Imports : ![]() Zitat:
Und die anderen Methoden haben fast alle den wichtigsten Parameter als Ersten, somit kann ich es als Methode in einen Record verschieben, und die Methode einfach als "external" deklarieren, womit dieser Parameter zum Self wird und direkt auf die DLL verweist. Standard-Oprtationen ala ADD, SUB und MUL, lassen sich dann zusätzlich auch schön in ClassOperator kapseln. Die Grundfunktionen ließen sich dann also wie beim normalen Integer benutzen. --- Es gab Anfangs sehr viele Fehler im Compilier, siehe ![]() Es handelte sich um folgene 3 Arten von Fehlern: overloaded functions with typeless parameters
Delphi-Quellcode:
NInts.NSet(var A: IInteger; const B; Size: Integer; Bits: Integer) name 'NInts_NSet_IIBInIn',
[Fehler] DECMath.dpr(66): Es existiert keine überladene Version von 'NSet' mit dieser Parameterliste. unnecessary overload and parameters not declared
Delphi-Quellcode:
NECBuild name 'NECBuild_XXX',
[Fehler] DECMath.dpr(625): Es existiert keine überladene Version von 'NECBuild' mit dieser Parameterliste. not overload, but still parameters declared
Delphi-Quellcode:
NInts.NCat(var A: IInteger; const B: IIntegerArray; Bits: Integer) name 'NInts_NCat_IIIAIn',
[Fehler] DECMath.dpr(109): ',' oder ';' erwartet, aber '(' gefunden [Fehler] DECMath.dpr(109): '=' erwartet, aber ';' gefunden [Fehler] DECMath.dpr(109): '=' erwartet, aber ')' gefunden [Fehler] DECMath.dpr(109): Undefinierter Bezeichner: 'name' [Fehler] DECMath.dpr(109): Inkompatible Typen: 'Integer' und 'String' [Fehler] DECMath.dpr(110): '=' erwartet, aber '.' gefunden ... Erstmal habe ich ein SharedMemory eingerichtet, womit es keine Probleme mit dynamischen Arrays und keine grundsätzlichen Probleme mit den DelphiStrings mehr geben sollte. Es gibt nun also die nur noch zwei Wrapper-Methoden, für die untypisierten Parameter. Ja, da könnte ich mit einem JMP in Assembler den einen Rücksprung des Wrappers einsparen, allerdings wäre dort der Aufwand höher im Assembler die richtige überladene Methode zu treffen. Dann gibt es eine Methode, wo ich aus einem Objekt ein Interface mache, durch eine zurätzliche Ableitung und cast des Result als Interface, wo sich nicht viel optimieren lässt. bzw. es ist bestimmt den Aufwand nicht wert.
Delphi-Quellcode:
function Primes: TSmallPrimeSieve;
wurde zu
Delphi-Quellcode:
(natürlich fehlt noch der Hook, um die Klassen auszutauschen, damit beim Create in der DCU der richtige Typ erzeugt wird)
type
ISmallPrimeSieve = interface ['{897D56D7-7514-4473-917E-3DEFCD9A54E3}'] function MinPrime: Cardinal; // min. Prime, allways 2 function MaxPrime: Cardinal; // max. possible Prime, dependend from Compiler Version function MinIndex: Cardinal; // min. Index, allways 1 function MaxIndex: Cardinal; // max. Index, see MaxPrime function Count(LowerBound, UpperBound: Cardinal): Cardinal; // compute Primecount beetwen Bounds function IndexOf(Value: Cardinal; LowerBound: Boolean{$IFDEF VER_D4H} = False{$ENDIF}): Cardinal; // give Primeindex of Value procedure LoadCache(const FileName: AnsiString); // load a Prime Cache procedure BuildCache(const FileName: AnsiString; Bound: Cardinal); // create and save a Cache function GetPrime(Index: Cardinal): Cardinal; property Prime[Index: Cardinal]: Cardinal read GetPrime; default; // return Prime with Index function CacheMaxPrime: Cardinal; // max. cached Prime function CacheMaxIndex: Cardinal; // max. cached Index of max. Prime // cached min. Values are allways equal to MinPrime, MinIndex end; TSmallPrimeSieveIntf = class(TSmallPrimeSieve, ISmallPrimeSieve) function MinPrime: Cardinal; function MaxPrime: Cardinal; function MinIndex: Cardinal; function MaxIndex: Cardinal; function GetPrime(Index: Cardinal): Cardinal; function CacheMaxPrime: Cardinal; function CacheMaxIndex: Cardinal; end; function PrimesIntf: ISmallPrimeSieve; begin Result := Primes as ISmallPrimeSieve; end; exports PrimesIntf name 'Prime_Primes', IsPrime name 'Prime_IsPrime'; Da sich seit Delphi 2009 die AnsiString intern verändert haben, muß ich dort unbedingt noch etwas anpassen. Jenes bezieht sich aber nur auf die wenigen
Delphi-Quellcode:
.
function NStr(x: Interface): AnsiString;
Delphi 7:
Delphi-Quellcode:
Delphi 11.3
type
PStrRec = ^StrRec; StrRec = packed record refCnt: Longint; length: Longint; end;
Delphi-Quellcode:
Const-Parameter in die DLL rein, stellen nahezu keine Probleme dar,
type
// For System.pas internal use only. // Note, this type is duplicated in getmem.inc for diagnostic purposes. Keep in sync. PStrRec = ^StrRec; StrRec = packed record {$IF defined(CPU64BITS)} _Padding: Integer; // Make 16 byte align for payload.. {$ENDIF} codePage: Word; elemSize: Word; refCnt: Integer; length: Integer; end; da die zusätzlichen Felder für das alte Delphi praktisch unsichtbar/irrelevant sind. Aber als Funktion-Result sieht das anders aus. Da hätte ich die Wahl es via Wrapper auf WideString zu casten. Allerdings werde ich hier das ![]() und dort aus dem Delphi7-AnsiString in NeuesDelphi-AnsiString erzeugen. Denn das neue Delphi würde knallen, wenn es auf die nicht-vorhandenen Felder eines "alten" String zugreifen will -> BufferOverflow. Außerdem stimmt die Brechnung StringPointer->MemoryBlock nicht überein und es würde spätestens neuen Delphi beim Freigeben des String in LStrClr->FreeMem knallen. Es gibt aber noch ein paar weitere Hindernisse, mit anderen zu teilenden Dingen. Exception-Klassen und andere übergebene Klassen und Objekte, wie z.B. TStream. Siehe meine "TODO" bzw. Shared-Liste in ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:34 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