AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

DLL Schnitstelle

Ein Thema von hewy · begonnen am 10. Jul 2020 · letzter Beitrag vom 7. Aug 2020
Antwort Antwort
Seite 4 von 4   « Erste     234
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.960 Beiträge
 
Delphi 10.4 Sydney
 
#31

AW: DLL Schnitstelle

  Alt 12. Jul 2020, 12:49
Und wo ich schonmal am rumranten bin:
Zum Kuckuck, gebe den Buffer gefälligst wieder frei mit se_free().
Einfach mal die Doku lesen, die du selber im ersten Beitrag zum VB Beispiel gepostet hast.

Internet kann für heute zu...
  Mit Zitat antworten Zitat
AuronTLG

Registriert seit: 2. Mai 2018
165 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
AuronTLG

Registriert seit: 2. Mai 2018
165 Beiträge
 
Delphi 10.4 Sydney
 
#33

AW: DLL Schnitstelle

  Alt 4. Aug 2020, 13:46
Ich bin gerade ein ganzes Stück weiter gekommen.
Das mit den Datentypen hat sich vermutlich erledigt und lag an etwas anderem. Authentifizieren hat funktioniert.
Interessant wird es hingegen beim Absturzproblem:

Ich habe den Aufruf von "AuthentifiziereBenutzer" mal zum Spaß in einen Timer gesteckt und im Button nur noch den Timer aktiviert.
In diesem Falle kommt es konsistent nicht zum Absturz, während direkt im Button es konsistent IMMER zum Absturz kommt.

Nun stellt sich für mich die große Frage, warum?

Im Debugger zumindest kam der katastrophale Fehler im Wndproc, was insofern Sinn machen würde, dass der TButton eine TWinControl ist, während der Timer eine TComponent ist.
Nur bin ich etwas ratlos, was genau überhaupt schiefgeht.

EDIT: TSpeedButton machts auch. Alles, was keine TWinControl ist, funktioniert.

Geändert von AuronTLG ( 4. Aug 2020 um 14:22 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.114 Beiträge
 
Delphi 11 Alexandria
 
#34

AW: DLL Schnitstelle

  Alt 4. Aug 2020, 14:28
Zitat:
Delphi-Quellcode:
Function StringToPByteArray(Nummer : AnsiString) : PByteArray;
Var AByteArray : TBytes;
    I : Integer;

Begin
AByteArray := System.SysUtils.TEncoding.ANSI.GetBytes(Nummer);
Result := @AByteArray;
End;
Sowas kann niemals funktionieren. (und wenn doch, dann hast zufällig Glück, dass noch niemand den Speicher überschrieb)

Das dynamische Array "AByteArray" wird am Ende der Funktion freigegeben, somit zeigt der Zeiger auf alten/ungültigen Mist.



Außerdem zeigt Result garnicht auf ein Byte-Array, sondern auf die Variable, die auf ein Byte-Array zeigt.
Result := @AByteArray[0];
Aber, wie schon gesagt, sind Variable und das Array nach dem END verschwunden und der Zeiger zeigt so oder so nur auf Mist.

Lösung: Via GetMem Speicher reservieren (bei DLLs nur unter Verwendung von ShareMem), dort die Array-Daten reinkopieren, und später nicht vergessen den Speicher wieder freizugeben.
Oder VirtualAlloc, GlobalMem oder einen anderen "globalen" Speichermanager verwenden, wie z.B. den aus'm Ole32/OleAuth.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu ( 4. Aug 2020 um 14:33 Uhr)
  Mit Zitat antworten Zitat
AuronTLG

Registriert seit: 2. Mai 2018
165 Beiträge
 
Delphi 10.4 Sydney
 
#35

AW: DLL Schnitstelle

  Alt 4. Aug 2020, 14:42
Im Prinzip habe ich festgestellt, dass die ganze Function unnötig ist.
Dank dir weiß ich nun auch im Detail, warum sie nicht funktioniert hat.

Das ByteArray, was erwartet wird, ist tatsächlich einfach nur ein Array von Zahlen, weswegen das Ganze wesentlich einfacher zu lösen war... Einfach ein Bytearray füllen und den Zeiger darauf mit der passenden Länge übergeben und es läuft.

Die einzige offene Frage, die ich momentan habe, ist der Grund für das Absturzphänomen, was aber keine sonderlich quälende Frage ist, da die Lösung darin besteht, die DLL-Aufrufe nicht mit TWinControl-TButtons durchzuführen, welche ich sowieso nicht verwende.
  Mit Zitat antworten Zitat
AuronTLG

Registriert seit: 2. Mai 2018
165 Beiträge
 
Delphi 10.4 Sydney
 
#36

AW: DLL Schnitstelle

  Alt 5. Aug 2020, 15:29
Ein neuer Tag, ein neues Problem mit der Schnittstelle...

Ich habe folgende DLL-Methode:
Code:
se_result_t se_readLogMessage   (   uint8_t **    logMessage,
uint32_t *    logMessageLength
)      
Reads a log message that bases on the last log message parts that have been produced and processed by the Secure Element.

Parameters
[out]   logMessage   contains the last log message that the Secure Element has produced [REQUIRED] If successfully executed, the buffer has to freed by the function caller [se_free()].
[out]   logMessageLength   length of the array that represents the last log message [REQUIRED]
Das widerliche daran ist der Datentyp "uint8_t **", was meines Verständnisses nach in C die Darstellung eines Arrays von Byte-Arrays ist. Also vergleichbar mit char **, für welches in Delphi ja bereits der Typ PPAnsiChar bereitgestellt wird. Ich bekomme einen Pointer, der auf den ersten PByteArray zeigt sowie praktisch die Anzahl der PByteArrays.

Mein derzeitiger Ansatz sieht wie folgt aus:

Ich deklariere mir analog einen eigenen Typ "PPByteArray":
Code:
Type PPByteArray = ^PByteArray
Habe ich dann meinen PPByteArray "PPA" und dessen Länge erhalten, so durchlaufe ich dieses und lege die einzelnen PByteArray in einem Array of PByteArray ab:
Code:
PBArray   : Array of PByteArray;

For I := 0 to Laenge - 1
  Do Begin
     PBArray[I] := PPA^;
     Inc(PPA);
     End;
Ab diesem Zeitpunkt sollte ich theoretisch mit den PByteArrays standardmäßig verfahren können. In der Praxis kommt aber letztendlich ein Byte-Salat raus, der definitiv falsche Speicheradressen enthält.

Dementsprechend würde mich mal interessieren, ob in meinen Überlegungen bereits Schwachsinn drin steckt oder ob das tatsächlich der richtige Umgang mit dem C-Datentyp "uint8_t ** ist. Ich musste mich bisher nur sehr selten mit derlei Pointern auseinandersetzen und habe auch nie C gelernt, weswegen mir das etwas Schwierigkeiten bereitet.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.114 Beiträge
 
Delphi 11 Alexandria
 
#37

AW: DLL Schnitstelle

  Alt 5. Aug 2020, 15:54
Zitat:
uint8_t **
Sowas kenn ich auch von einem Hersteller, der intern so geile C++-Strings benutzt. (das sind wohl Objekte oder zumindestens auch sowas ähnliches wie Delphi-Strings, also ein Zeiger auf eine Struktur).

Geil ist daran, dass er eben nicht den String rausgibt, sondern einen Zeiger auf seine Variable, die dann auf den String zeigt.


Kann auch gut sein, dass du dir hier auch in deine Variable einen Zeiger reinschreiben lässt, der auf eine Variable zeigt, in der dann der String drin steht.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  Mit Zitat antworten Zitat
AuronTLG

Registriert seit: 2. Mai 2018
165 Beiträge
 
Delphi 10.4 Sydney
 
#38

AW: DLL Schnitstelle

  Alt 7. Aug 2020, 09:47
So ähnlich wars letztendlich auch:

Im Prinzip hat ein PByteArray als Parameter ausgereicht, aus dessem angezeigten ByteArray der zurückgegebenen Länge ich dann die Werte auslesen konnte.
PPByteArray etc war alles unnötig. Ob "uint8_t *" oder "uint8_t **" macht für Delphi keinen Unterschied.

Was ein Schwachsinn...
  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 04:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf