Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte » 

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   DLL Schnitstelle (https://www.delphipraxis.net/204889-dll-schnitstelle.html)

hewy 10. Jul 2020 14:45


DLL Schnitstelle
 
Hallo,

Seit mehreren Tagen brüte ich nun schon über folgendes:
Als nicht DLL und auch nicht C/C++ Spezi habe ich hier eine Frage zum Aufruf einer DLL Funktion aus Delphi.
Hier die ‘c’ Seite:

Code:
SE_API_IMPL(se_result_t, se_getCertificationId)(char **certificationId,   uint32_t *certificationIdLength)
Wie würde das Delphi Gegenstück dazu aussehen?

Die DLL function spreche ich in Delphi so an
Delphi-Quellcode:
function se_getCertificationId(var certificationId: PAnsiChar; certificationIdLength: Cardinal): Cardinal; cdecl; external 'se-api-c.dll';
Sicher ein Klacks komme aber hier nicht weiter und wäre daher sehr dankbar für eine Hint oder besser
Code:
In VB.Net sieht es so aus. Brauche aber das Delphi äquivalent.
        ' Get certification ID as assigned by BSI ("BSI-K-TR-0374-2019" for cryptovision TSE).
        ' @param[out] certificationId      Returned identifier string (Not null terminated) [REQUIRED]
        '                                  If successfully executed, the buffer has to freed by the function caller [@ref se_free()].
        ' @param[out] certificationIdLength length of the returned identifier string [REQUIRED]
        ' @return @ref ExecutionOk         execution of the function has been successful
        ' @return @ref ErrorSECommunicationFailed Secure Element communication failed
        ' @since v2.1
        ' se_result_t se_getCertificationId(char**certificationId, uint32_t*certificationIdLength);
        <DllImport("se-api-c.dll", EntryPoint:="se_getCertificationId", CharSet:=CharSet.Ansi)>
        Private Function GetCertificationIdSub(ByRef certificationId As IntPtr,
                                               ByRef certificationIdLength As Integer) As SeReturnCode
        End Function
        Public Structure GetCertificationIdReturn
            Public ReturnCode As SeReturnCode
            Public certificationId As String
        End Structure
        Public Function GetCertificationId()
            Dim ReturnStruct As GetCertificationIdReturn
            Dim certificationId As IntPtr
            Dim certificationIdLength As Integer
            ReturnStruct.ReturnCode = GetCertificationIdSub(certificationId, certificationIdLength)
            If SeReturnCode.ExecutionOk = ReturnStruct.ReturnCode Then
                ReturnStruct.certificationId = PtrToStringAnsiAndFree(certificationId, certificationIdLength)
            Else
                ReturnStruct.certificationId = String.Empty
            End If
            Return ReturnStruct
        End Function
Vielen Dank für jegliche Hilfe
Heiri

TiGü 10. Jul 2020 15:01

AW: DLL Schnitstelle
 
Code:
SE_API_IMPL(se_result_t, se_getCertificationId)(char **certificationId, uint32_t *certificationIdLength)
-> declare se_getCertificationId as function (pointer to pointer to char, pointer to uint32_t) returning se_result_t
Delphi-Quellcode:
type
  se_result_t = Cardinal; //? musst du in der Doku gucken was se_result_t sein soll
  PUInt32 = ^System.UInt32;
  PPByte = ^System.PByte;


function se_getCertificationId(var certificationId: PAnsiChar; certificationIdLength: PUInt32): se_result_t ; cdecl; external 'se-api-c.dll';
//oder
function se_getCertificationId(var certificationId: PAnsiChar; var certificationIdLength: UInt32): se_result_t ; cdecl; external 'se-api-c.dll';
// probiere auch mal so, wenn certificationID eh ne Zahl zwischen 0 und 255 laut Doku ist:
function se_getCertificationId(var certificationId: PByte; var certificationIdLength: UInt32): se_result_t ; cdecl; external 'se-api-c.dll';
// gerne auch
function se_getCertificationId(certificationId: PPByte; certificationIdLength: PUInt32): se_result_t ; cdecl; external 'se-api-c.dll';

hewy 10. Jul 2020 15:30

AW: DLL Schnitstelle
 
Oh vielen Dank für deine Antwort.
- se_result_t enthält ein Fehler Code falls es nicht korrekt durch läuft 0. Bei mir kommt immer 'fehlender Parameter'
- var certificationId: PAnsiChar sollte die gesuchte ID zurückliefern bei der VB Version bekomme ich das hier 'BSI-K-TR-0000-2019' bei Delphi eben noch nicht! Humm
Heiri

TiGü 10. Jul 2020 15:46

AW: DLL Schnitstelle
 
Zeig doch mal deinen Quelltext, wo du die Funktion aufrufst.
Hast du alle beide PAnsiChar-Varianten mal durchprobiert?

EDIT: Ändere mal bei se_result_t von Cardinal zu einen Int32.
Da du nicht die Definition aus dem C-Header gepostet hast, nehme ich einfach mal an, dass da ggf. auch negative Werte rausfallen können?!

himitsu 10. Jul 2020 15:53

AW: DLL Schnitstelle
 
Sicher, dass es cdecl oder nicht vielleicht stdcall ist?

Wie sieht denn SE_API_IMPL aus?




[OT]
Hach, wie schön es bald mit 64 Bit wird ... da gibt's nur noch eine Convention (die fast wie bei unserem Pascal aussieht :stupid:)

hewy 11. Jul 2020 10:21

AW: DLL Schnitstelle
 
Vielen Dank für eure Hilfe versuche.

Jetzt habe ich auch begriffen wie man hier korrekt Code schnipsel einfügt!
Insgesammt sind es über 50 Funktionen, die meisten sind ok nur 'se_getCertificationId' will nicht so recht.
So sehen die Einbindungen der DLL Funktionen aus:
Delphi-Quellcode:
function se_getImplementationVersionString(): PAnsiChar; cdecl; external 'se-api-c.dll';
function se_getImplementationVersion(): PAnsiChar; cdecl; external 'se-api-c.dll';
function se_getUniqueId(): PAnsiChar; cdecl; external 'se-api-c.dll';

function se_getCertificationId(var certificationId: PAnsiChar; certificationIdLength: Cardinal): Cardinal; cdecl; external 'se-api-c.dll';

function se_getLifeCycleState(var lcs: Cardinal): Cardinal; cdecl; external 'se-api-c.dll';
function se_getMaxNumberOfClients(var maxNumberClients: Cardinal): Cardinal; cdecl; external 'se-api-c.dll';
Und hier die Aufrufe dazu:
Delphi-Quellcode:
function SeGetPinStatus(var PINState: Cardinal): TSeReturnCode;
function SeGetUniqueId: string;

function SeGetCertificationId(var CertificationId: string): TSeReturnCode;

function SeAuthenticateUser(UserId: string; PIN: array of Byte; var AuthenticationResult: TSeAuthenticationResult; var RemainingRetrie: ShortInt): TSeReturnCode;
function SeGetLifeCycleState(var lcs: TSeLifeCycleState): TSeReturnCode;
Und die Implementation dazu (Hier mache ich eiregend etwas falsch und komme nicht dahinter was wie gemacht werden muss.)

Delphi-Quellcode:
function SeGetCertificationId(var CertificationId: string): TSeReturnCode;
var
  PCertificationID: PAnsiChar;
  PCurrent: PAnsiChar;
  CertificationIDLength: Cardinal;
  i: Cardinal;
begin
  PCertificationID := nil;

  // VB übergibt PCertificationID = &H000000000 und CertificationIDLength = 0

  Result := TSeReturnCode(se_getCertificationID(PCertificationID, CertificationIDLength));

  // Zurück bekomme ich im VB Code BSI-K-TR-0000-2019 für PCertificationID und 18 für CertificationIDLength

  // Mit Delphi und der Zeile oben einen Fehlercode

  //    Da werde ich die Parameter entsprechend übernehme sobalt
  //    mir se_getCertificationID was brauchbares liefert.
  //    Aktuell erhalte ich hier Access Violation oder der Result code sagt
  //    etwas von 'missing parameter'

end;
Vielen Dank schon mal für die Auswertung meiner Angaben und etwelche wie was wo zu tun ist Hints!

venice2 11. Jul 2020 10:46

AW: DLL Schnitstelle
 
Das.
Delphi-Quellcode:
function se_getCertificationId(certificationId: PPByte; certificationIdLength: PUInt32): se_result_t ; cdecl; external 'se-api-c.dll';


kann nur ins leere laufen denn ByRef ist immer var in Delphi ByVal ist einfach ein Parameter der übergeben wird.
Und dann was denn nun?

Delphi-Quellcode:
PCertificationID: PAnsiChar;
oder
Delphi-Quellcode:
CertificationId: string
beides geht auf keinen Fall wenn schon dann
Delphi-Quellcode:
PCertificationID: PAnsiChar;
entfernen und Rückgabe ist
Delphi-Quellcode:
CertificationId: string

Wenn CertificationId ein Pointer auf AnsiString ist (siehe PtrToStringAnsiAndFree) dann bitte
Delphi-Quellcode:
CertificationID: PAnsiChar
und nicht
Delphi-Quellcode:
CertificationID: string
.

Alles durcheinander geworfen sorry.
Siehe

Delphi-Quellcode:
function SeGetCertificationId(var CertificationId: string): TSeReturnCode;

und
Delphi-Quellcode:
function SeGetCertificationId(var CertificationId: PAnsiChar): TSeReturnCode;


Die Definition
Delphi-Quellcode:
PCertificationID: PAnsiChar;

ist dann unsinnig.

Korrekt wäre das ohne Gewähr.

Delphi-Quellcode:
function SeGetCertificationId(var CertificationId: PAnsiChar): TSeReturnCode;
var
  // PCertificationID: PAnsiChar; // Quatsch
  // PCurrent: PAnsiChar; wird nicht verwendet
  CertificationIDLength: Cardinal;
  // i: Cardinal; wird nicht verwendet
begin
  // PCertificationID := nil; Quatsch

  // VB übergibt PCertificationID = &H000000000 und CertificationIDLength = 0

  Result := TSeReturnCode(se_getCertificationID(CertificationID, CertificationIDLength));

  // Zurück bekomme ich im VB Code BSI-K-TR-0000-2019 für PCertificationID und 18 für CertificationIDLength

  // Mit Delphi und der Zeile oben einen Fehlercode

  // Da werde ich die Parameter entsprechend übernehme sobalt
  // mir se_getCertificationID was brauchbares liefert.
  // Aktuell erhalte ich hier Access Violation oder der Result code sagt
  // etwas von 'missing parameter'

end;
Nochmal
Delphi-Quellcode:
var certificationId: PAnsiChar
oder
Delphi-Quellcode:
var certificationId: string
entscheide dich einfach mal.

Delphi-Quellcode:
function se_getCertificationId(var certificationId: PAnsiChar; certificationIdLength: Cardinal): Cardinal; cdecl; external 'se-api-c.dll';

himitsu 11. Jul 2020 11:20

AW: DLL Schnitstelle
 
Das PAnsiChar <> String UnicodeString (seit Delphi 2009) wollte ich auch grade ansprechen.

Zitat:

Delphi-Quellcode:
function SeGetCertificationId(var CertificationId: string): TSeReturnCode;
var
  PCertificationID: PAnsiChar;
  PCurrent: PAnsiChar;
  CertificationIDLength: Cardinal;
  i: Cardinal;
begin
  PCertificationID := nil;

  // VB übergibt PCertificationID = &H000000000 und CertificationIDLength = 0

  Result := TSeReturnCode(se_getCertificationID(PCertificationID, CertificationIDLength));
  ...

Der Code ist so nichtmal kompilierbar.
Wieso ignoriert hier jemand die Compilerwarnungen?
Und wenn VB das macht, warum du nicht auch?

CertificationIDLength wurde nicht initialisiert
PCertificationID = string -> PAnsiChar

Und wenn VB das macht, dann vermutlich um erstmal im Result die nötige Länge abzufragen, welche für einen weiteren Aufruf benutzt wird.

Man kann alternativ auch blind den Speicher auf eine Länge festlegen, die "immer" ausreichend wäre,
und anschließend auf das zurück ändern, was wirklich benutzt wurde.

Probleme:
* falsche Typen (ANSI <> Unicode)
* falsche Benutzung (ungültige Parameter)

Entweder intern mit ANSI arbeiten und umkopieren oder die umgebende Funktion mit einem AnsiString bauen.

hewy 11. Jul 2020 11:28

AW: DLL Schnitstelle
 
Vielen Dank venice2,

hilft mir schon mal weiter.
Delphi-Quellcode:
function SeGetCertificationId(var CertificationId: string): TSeReturnCode;
var
  PCertificationID: PAnsiChar;
  PCurrent: PAnsiChar;
  CertificationIDLength: Cardinal;
  i: Cardinal;
begin
  PCertificationID := nil;

  // VB übergibt PCertificationID = &H000000000 und CertificationIDLength = 0

  Result := TSeReturnCode(se_getCertificationID(PCertificationID, CertificationIDLength));

  // Zurück bekomme ich im VB Code BSI-K-TR-0000-2019 für PCertificationID und 18 für CertificationIDLength

  // Der var Parameter im Header der Funktion sollte für meine Zwecke schon [B]string[/B] sein

  // Dann müsste ich halt dies entsprechend konvertieren.
  // Zum Beispiel so
  CertificationId := String(AnsiString(PCertificationID)); // Oder sehe ich das falsch?

  // Nur eben die Funktion se_getCertificationID liefert nichts brauchbares in Delphi
  // Also müsste wohl PCertificationID: PAnsiChar; anders definiert sein oder anders
  // initialisiert werden, [B]da liegt offenbar mein Problem. [/B]

end;

venice2 11. Jul 2020 11:32

AW: DLL Schnitstelle
 
Ich würde den Kram so umschreiben wenn für CertificationIDLength keine Rückgabe erforderlich ist.

Zitat:

CertificationIDLength wurde nicht initialisiert
PCertificationID = string -> PAnsiChar
Delphi-Quellcode:
function SeGetCertificationId(var CertificationId: PAnsiChar; CertificationIDLength: Cardinal): TSeReturnCode;
Delphi-Quellcode:
if SeGetCertificationId(CertificationId, 0) = ExecutionOk then
  bla, bla
EDIT:
Delphi-Quellcode:
CertificationId := String(AnsiString(PCertificationID)); // Oder sehe ich das falsch?

Ja. Du benötigst die Variable PCertificationID nicht!
Die Rückgabe ist ein Pointer auf Ansistring (PAnsiChar) siehe (PtrToStringAnsiAndFree) kein String!


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:17 Uhr.
Seite 1 von 4  1 23     Letzte » 

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