AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Delphi 7 DLL-Exports überladener Methoden?

Ein Thema von himitsu · begonnen am 10. Sep 2023 · letzter Beitrag vom 17. Sep 2023
Antwort Antwort
Seite 2 von 2     12
mytbo

Registriert seit: 8. Jan 2007
472 Beiträge
 
#11

AW: Delphi 7 DLL-Exports überladener Methoden?

  Alt 10. Sep 2023, 16:53
Die genaue Deklaration kann ich nicht sehen.
Hab ja nur die DCU und das abgespeckte "so in etwa"-Interface der Unit, ...
Hast du es schon mit DCU32INT versucht?

Bis bald...
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.104 Beiträge
 
Delphi 12 Athens
 
#12

AW: Delphi 7 DLL-Exports überladener Methoden?

  Alt 10. Sep 2023, 17:56
Ja (und Anderes), aber liefert nichts verwertbares.

Zitat:
unknown unit file
Except command $96 at $A9, but $41 found.
Except ...
...
[edit]
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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (10. Sep 2023 um 18:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.104 Beiträge
 
Delphi 12 Athens
 
#13

AW: Delphi 7 DLL-Exports überladener Methoden?

  Alt 10. Sep 2023, 19:53
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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.104 Beiträge
 
Delphi 12 Athens
 
#14

AW: Delphi 7 DLL-Exports überladener Methoden?

  Alt 13. Sep 2023, 10:48
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.

https://github.com/geheimniswelten/DECMath-Legacy
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (13. Sep 2023 um 10:52 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.104 Beiträge
 
Delphi 12 Athens
 
#15

AW: Delphi 7 DLL-Exports überladener Methoden?

  Alt 15. Sep 2023, 18:24
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 name 'xxx' nicht, aber später ging es plötzlich.
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.

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.



https://github.com/geheimniswelten/DECMath-Legacy
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)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (16. Sep 2023 um 00:36 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.104 Beiträge
 
Delphi 12 Athens
 
#16

[gelöst] Delphi 7 DLL-Exports überladener Methoden?

  Alt 16. Sep 2023, 20:09
Ahhhhhhhhhhhh, i werd' irre.


Hab die Gründe raus.
  • einmal zwei Fehler beim Kopieren (falscher TypBezeichner)
  • wenn bei einer Funktion kein overload deklariert ist, dann darf man keine Parameter angeben
  • selbst wenn eine Funktion eindeutig ist, aber dennoch mit overload deklariert wurde, müssen Parameter angegeben werden (auch wenn es unmenschlich Viele sind, die man gern weglassen würde)
  • typlose Var/Const-Parameter lassen sich nicht angeben ... also geht nur, wenn ohne overload und man sie weglassen kann



PS:
Also das compiliert hier unter D7:
Delphi-Quellcode:
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);
Selbst das kompiliert anstandslos,
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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (16. Sep 2023 um 20:18 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.104 Beiträge
 
Delphi 12 Athens
 
#17

[gelöst] Delphi 7 DLL-Exports überladener Methoden?

  Alt 16. Sep 2023, 20:14
[del]
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (16. Sep 2023 um 20:17 Uhr)
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
353 Beiträge
 
#18

AW: Delphi 7 DLL-Exports überladener Methoden?

  Alt 17. Sep 2023, 10:03
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.
Kas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.104 Beiträge
 
Delphi 12 Athens
 
#19

AW: Delphi 7 DLL-Exports überladener Methoden?

  Alt 17. Sep 2023, 12:41
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 : /Part_II/DECMath.dpr
Delphi 2006+ Imports : /Part_II/DECMath.pas


Zitat:
Delphi-Quellcode:
procedure NSet(var A: IInteger; B: Integer); overload;
procedure NSet(var A: IInteger; B: Int64); overload;
procedure NSet(var A: IInteger; B: Extended); overload;
procedure NSet(var A: IInteger; const B: IInteger = nil; Abs: Boolean = False); overload;
procedure NAdd(var A: IInteger; B: Integer); overload;
procedure NAdd(var A: IInteger; const B: IInteger); overload;
procedure NSub(var A: IInteger; B: Integer); overload;
procedure NSub(var A: IInteger; const B: IInteger); overload;
procedure NMul(var A: IInteger; B: Integer); overload;
procedure NMul(var A: IInteger; B: Int64); overload;
procedure NMul(var A: IInteger; const B: IInteger; C: Int64); overload;
procedure NMul(var A: IInteger; const B: IInteger; C: Integer); overload;
procedure NMul(var A: IInteger; const B: IInteger); overload;
function NStr(const A: IInteger; Base: TBase = 0): RetString; overload;
function NStr(const A: IInteger; const Format: TStrFormat): RetString; overload;
NStr als MyRec.ToString
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 Antwort #16, aber das ist nun behoben.
Es handelte sich um folgene 3 Arten von Fehlern:

overloaded functions with typeless parameters
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
NECBuild name 'NECBuild_XXX',
[Fehler] DECMath.dpr(625): Es existiert keine überladene Version von 'NECBuild' mit dieser Parameterliste.

not overload, but still parameters declared
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.

function Primes: TSmallPrimeSieve;
wurde zu
Delphi-Quellcode:
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';
(natürlich fehlt noch der Hook, um die Klassen auszutauschen, damit beim Create in der DCU der richtige Typ erzeugt wird)

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 function NStr(x: Interface): AnsiString; .

Delphi 7:
Delphi-Quellcode:
type
  PStrRec = ^StrRec;
  StrRec = packed record
    refCnt: Longint;
    length: Longint;
  end;
Delphi 11.3
Delphi-Quellcode:
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;
Const-Parameter in die DLL rein, stellen nahezu keine Probleme dar,
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 Delphi-Referenz durchsuchenSetString des neuen Delphi in die DLL durchreichen
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 \Part_II\DECMath.Shared.txt.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.

Geändert von himitsu (17. Sep 2023 um 12:54 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 13:10 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