Einzelnen Beitrag anzeigen

AuronTLG

Registriert seit: 2. Mai 2018
161 Beiträge
 
Delphi 10.4 Sydney
 
#32

AW: DLL Schnitstelle

  Alt 3. Aug 2020, 15:57
Ich schlage mich gerade mit dem selben Mist herum und hätte auch mal eine Frage:

Ich habe folgende Definition in der C-DLL:
Code:
se_result_t se_authenticateUser   (   const char *    userId,
uint32_t    userIdLength,
const uint8_t *    pin,
uint32_t    pinLength,
se_authentication_result_t *    authenticationResult,
int16_t *    remainingRetries
)
Anmerkung: Die DLL gibt es in sowohl als CDECL- als auch als STDCALL-Variante. Ich benutze logischerweise die STDCALL-Variante, während Hewy wohl die CDECL-Variante verwendet.
Weiterhin lade ich die DLL dynamisch über LoadLibrary.

Ich habe daraus folgende Definition für Delphi gemacht:
Code:
se_authenticateUser              = Function(userId : PAnsiChar; userIdLength : UInt32; pin : PByteArray; pinLength : UInt32;
                                             Var authenticationResult : SeAuthenticationResult; Var remainingRetries : PShortInt) : SeReturnCode; Stdcall;
Die eigentlich Zugriffsmethode, die ich dazwischengeschaltet habe, sieht dann folgendermaßen aus:
Code:
Function AuthentifiziereBenutzer(BenutzerID, BenutzerPIN : String; Var Ergebnis : SeAuthenticationResult; Var Versuche : ShortInt) : Boolean;
Var ReturnCode : SeReturnCode;
    PVersuche : PShortInt;
    ID        : PAnsiChar;
    PIN       : PByteArray;

Begin
Result := False;
PVersuche := @Versuche;

ID := PAnsiChar(AnsiString(BenutzerID));
PIN := StringToPByteArray(BenutzerPIN);

ReturnCode := Self.AuthenticateUser(ID, Length(BenutzerID), PIN, Length(BenutzerPIN), Ergebnis, PVersuche);
Versuche  := PVersuche^;
End;
Anmerkung: Unterer unwichtiger Teil der Methode ist abgeschnitten, also bitte nicht auf etwaiges Result etc fokussieren.

StringToPByteArray ist folgendermaßen implementiert:
Code:
Function StringToPByteArray(Nummer : AnsiString) : PByteArray;
Var AByteArray : TBytes;
    I         : Integer;

Begin
AByteArray := System.SysUtils.TEncoding.ANSI.GetBytes(Nummer);
Result := @AByteArray;
End;
Ich habe zwei Probleme damit:

1. Die Funktion liefert korrekt Rückgabewerte, aber die Authentifizierung klappt nicht trotz richtiger Zugangsdaten, was impliziert, dass etwas mit meinem übergebenen Datentypen nicht stimmt.

2. 1-2 Sekunden nach Ausführen dieser Funktion stürzt das gesamte Programm ab und schließt sich ohne weitere Warnung. Hier bin ich etwas ratlos. Debugger hält mit einer Zugriffsverletzung ganz unten im internen TControl.WndProc an und bricht dann dermaßen katastrophal zusammen ("Aktuelle Debugger-Sitzung muss beendet werden...", "Systemresourcen erschöpft"), dass ich per Task Manager die Entwicklungsumgebung killen muss. Die Funktion wird in einem Button aufgerufen. Ich hoffe stark, dass dieser Punkt mit Punkt 1 zusammenhängt.

Meine Überlegungen:
PAnsiChar für "char *" ist logisch. Bei der Längenübergabe bin ich mir aber nicht ganz sicher, ob das so in Ordnung ist.
PByteArray für "uint8_t * & length"-Konstruktionen zur Übergabe von alphanumerischen Werten in die C DLL sollte generell korrekt sein, jedoch bin ich mir auch hier bei der Längenübergabe unsicher sowie bei meiner Umwandlung eines Eingabe-Strings in ein PByteArray. Eventuell wäre hier ebenfalls PAnsiChar sinnvoller?

Offensichtlich ist der Zugriff auf eine C-DLL von Delphi aus Neuland für mich, weswegen ziemlich dämliche Fehler nicht unwahrscheinlich sind.

Ich wäre für jede Hilfestellung dankbar.
  Mit Zitat antworten Zitat