Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   c DLL char++ übersetzen (https://www.delphipraxis.net/201991-c-dll-char-uebersetzen.html)

mfoerste 17. Sep 2019 11:04

c DLL char++ übersetzen
 
Hallo,
ich kenne mich leider nicht gut mit Zeigern aus und muss jetzt eine fremde dll einbinden, die viel mit Zeigern arbeitet. Funktionen ohne Zeiger vom Typ char** konnte ich erfolgreich einbinden, aber mit bekomme ich es einfach nicht übersetzt.

Nach vielen Stunden des vergebenen Suchens möchte nun hier um Hilfe bitten.

Die Dll (in c geschrieben) hat eine einfache function, die nur eine LogMessage und deren Länge zurückgibt. Die Definition ist laut Hersteller wie folgt:
Code:
short int readLogMessage(unsigned char **logMessage,
                         unsigned long int *logMessageLength);
Ich habe u. a. versucht, dies so zu übersetzen:
Code:
function readLogMessage(logMessage:ppAnsiChar;
                        logMessageLength:PWORD):integer;stdcall;external 'fremdedll.dll';
Um an die Logmessage zu kommen habe ich mir folgenden Code überlegt, der leider nicht wirklich funktioniert:
Code:
type
TArrayOfAnsiChar = array of AnsiChar;
pArrayOfAnsiChar = ^TArrayOfAnsiChar;

var
msg: ppAnsiChar;
ergebnis,i: integer;
pmsg : pArrayOfAnsiChar;
msgLength: pWord;
str : string;

begin
  new(msg);
  new(pmsg);
  new(msgLength);
  ergebnis := readLogMessage(msg,msgLength);
  memo1.lines.add(inttostr(msgLength^));
  pmsg := pointer(msg);
  str := '';
  for i := 0 to msgLength^-1  do
  begin
    str := str + pmsg^[i];
  end;
  ShowMessage(str);
end;
msgLength^ gibt 305 zurück, was laut Hersteller der dll wohl realistisch sein soll. str hat folgenden Inhalt:

'0‚'#1'-'#2#1#2#6#9#4#0#$7F#0#7#3#7#1#1'€'#$10'StartTransa ction'#$0081#$14'a'#0's'#0'i'#0'g'#0'n'#0't'#0's'# 0'e'#0'_'#0'd'#0'‚YB'#0'e'#0'l'#0'e'#0'g'#0'^'#0'7 '#0'5'#0'.'#0'3'#0'3'#0'_'#0'7'#0'.'#0'9'#0'9'#0'_ '#0'0'#0'.'#0'0'#0'0'#0'_'#0'0'#0'.'#0'0'#0'0'#0'_ '#0'0'#0'.'#0'0'#0'0'#0'^'#0'1'#0'0'#0'.'#0'0'#0'0 '#0':'#0'B'#0'a'#0'r'#0'_'#0'5'#0'.'#0'0ƒ'#$E'K'#0 'a'#0's'#0's'#0'e'#0'n'#0'b'#0'…'#1' '#4' ÎŒ6,qPò³'#$19'Y½ZDHâo'#$13'ŠÍçBNhéh‹m¼Öœ™\0'#$A#6# 8'*†HÎ='#4#3#2#2#1'!'#$17#$D'190914143703Z'#4'G0E' #2'!'#0#$008F'øA$™I'#$0081')Ó–8'#$1D'šáÉ”¯oEÛâYEÛÓ 9#B[/ŒN'#2' *~§ƒs#'#5'(Øp\¬¢ívO'#$14'¥@ÉtÚÉÄFËMH_u¨¬'

Teilweise sieht es wie nullterminierte Strings aus.
Jemand eine Idee wie es richtig funktioniert?

KodeZwerg 17. Sep 2019 11:18

AW: c DLL char++ übersetzen
 
Hi, ich kenne Deine Bibliothek leider nicht aber ich nutz bei solch einen Aufruf (unsigned char) = Byte anstelle von AnsiChar.

Dein output sieht eher nach einem WideString anstelle AnsiString aus.... hmmmm

DeddyH 17. Sep 2019 11:33

AW: c DLL char++ übersetzen
 
Wie es scheint geben alle TSEs solch eine Grütze aus. Mir konnte bislang leider auch noch niemand sagen, ob das so stimmt, oder zumindest einen in C ausgelesenen Vergleichswert zukommen lassen. Ansonsten schau einmal hier: https://www.delphipraxis.net/201926-...ersetzung.html

hoika 17. Sep 2019 11:51

AW: c DLL char++ übersetzen
 
Hallo,
müßte das nicht so aussehen?

char ** P
var p: PAnsiChar

Also Zeiger auf einen Zeiger.

Siehe auch hier
https://stackoverflow.com/questions/...char-to-delphi

samso 17. Sep 2019 11:56

AW: c DLL char++ übersetzen
 
Üblicherweise sind solche Zeiger auf Zeiger ein Hinweis darauf, dass hier die DLL eine Variable beschreiben möchte. Deshalb würde ich schon readLogMessage anders formulieren.

Vielleicht geht es so:

Delphi-Quellcode:
function readLogMessage(var logMessage: pAnsiChar;
                        var logMessageLength:Integer):integer;stdcall;external 'fremdedll.dll';
und dann

Delphi-Quellcode:
var
 msg: pAnsiChar;
 ergebnis: integer;
 msgLength: integer;
 str : Ansistring;

begin
  ergebnis := readLogMessage(msg,msgLength);
  memo1.lines.add(inttostr(msgLength));
  SetLength(str, msgLength);
  AnsiStrings.StrLCopy(PAnsiChar(str), msg, msgLength);
  ShowMessage(String(str));
end;

samso 17. Sep 2019 12:12

AW: c DLL char++ übersetzen
 
Zitat:

Zitat von DeddyH (Beitrag 1446597)
Wie es scheint geben alle TSEs solch eine Grütze aus.

Damit ich nicht dumm sterben muss: Was ist ein TSE?

DeddyH 17. Sep 2019 12:22

AW: c DLL char++ übersetzen
 
TSE = Technische Sicherheitseinrichtung, dient zur digitalen Signatur von Kassenvorgängen (sehr verkürzt ausgedrückt).

mfoerste 17. Sep 2019 12:48

AW: c DLL char++ übersetzen
 
Der Hersteller gab mir noch folgenden Hinweis:

readLogMessage wird die Speicheradresse eines Zeigers auf ein array von chars und die Speicheradresse eines long integers übergeben. Nach dem erfolgreichen Aufruf der Funktion, Zeigt der übergebene Zeiger auf ein array von chars und logMessageLength enthält die länge dieses arrays.

DeddyH 17. Sep 2019 12:54

AW: c DLL char++ übersetzen
 
Hast Du #5 einmal versucht?

mfoerste 17. Sep 2019 12:56

AW: c DLL char++ übersetzen
 
Immer wenn ich mit einem Zitat antworte kommt die Meldung, dass diese erst durch einen Mod freigeschaltet werden muss.

Also ohne Zitat:
ja, ich habe #5 versucht und erhielt folgendes Ergebnis:

Name Wert
str '0‚'#1'-'#2#1#2#6#9#4#0#0'N'#0'_'#0'I'#0'N'#0'F'#0'O'#0#0# 0#0#0'½'#4'ïþ'#0#0#1#0#$A#0#6#0'd'#1'ºG'#0#0#$A#0' d'#1'ºG?'#0#0#0#0#0#0#0#4#0#4#0#2#0#0#0#0#0#0#0#0# 0#0#0#0#0#0#0'ö'#2#0#0#1#0'S'#0't'#0'r'#0'i'#0'n'# 0'g'#0'F'#0'i'#0'l'#0'e'#0'I'#0'n'#0'f'#0'o'#0#0#0 'Ò'#2#0#0#1#0'0'#0'4'#0'0'#0'7'#0'0'#0'4'#0'B'#0'0 '#0#0#0'L'#0#$16#0#1#0'C'#0'o'#0'm'#0'p'#0'a'#0'n' #0'y'#0'N'#0'a'#0'm'#0'e'#0#0#0#0#0'M'#0'i'#0'c'#0 'r'#0'o'#0's'#0'o'#0'f'#0't'#0' '#0'C'#0'o'#0'r'#0'p'#0'o'#0'r'#0'a'#0't'#0'i'#0'o '#0'n'#0#0#0'd'#0#$1E#0#1#0'F'#0'i'#0'l'#0'e'#0'D' #0'e'#0's'#0'c'#0'r'#0'i'#0'p'#0't'#0'i'#0'o'#0'n' #0#0#0#0#0'B'#0'i'#0'b'#0'l'#0'i'#0'o'#0't'#0'h'#0 'e'#0'k'#0' '#0'f'#0'ü'#0'r'#0' '#0'S'#0't'#0'e'#0'u'#0'e'#0'r'#0'e'#0'l'#0'e'#0#0

DeddyH 17. Sep 2019 13:00

AW: c DLL char++ übersetzen
 
Wie gesagt, bei mir sieht das ähnlich aus. Es gibt doch bestimmt eine ähnliche Funktion für ProcessData, was kommt denn da heraus (ich muss da allerdings explizit alle #0 herausfiltern)?

samso 17. Sep 2019 13:09

AW: c DLL char++ übersetzen
 
Wir sind uns einig, dass das komisch aussieht. Vielleicht doch UTF-16?
Delphi-Quellcode:
function readLogMessage(var logMessage: pChar;
                        var logMessageLength:Integer):integer;stdcall;external 'fremdedll.dll';
Delphi-Quellcode:
var
 msg: pChar;
 ergebnis: integer;
 msgLength: integer;
 str : String;
begin
  ergebnis := readLogMessage(msg, msgLength);
  memo1.lines.add(inttostr(msgLength));
  SetString(str, msg, msgLength);
  ShowMessage(str);
end;

mfoerste 17. Sep 2019 13:11

AW: c DLL char++ übersetzen
 
Da habe ich mich ehrlich gesagt noch nicht herangetraut. Ich wollte mit einer einfachen Funktion anfangen, um erst einmal das char** umgesetzt zu bekommen.

Es beruhigt mich ein wenig, dass ich nicht alleine diese Ergebnisse habe.

Gibt noch die function exportSerialNumbers

Code:
short int exportSerialNumbers(unsigned char **serialNumbers,
                              unsigned long int *serialNumbersLength);
serialNumbers out REQUIRED The serial number(s) of the SE API. The serial number(s) SHALL be encoded in the TLV structure defined in BSI TR-03151.
serialNumbersLength out REQUIRED Length of the array that represents the serial number(s).

Vielleicht sollte ich es hiermit mal probieren.

mfoerste 17. Sep 2019 13:17

AW: c DLL char++ übersetzen
 
Mit UTF-16 wird's chinesisch, wobei einige Teile wiederum gut aussehen:

Name Wert
str '舰ⴁĂ'#$0602'Љ缀܀܃āႀ瑓牡呴慲獮捡楴湯ᒁasigntse_d如Beleg^75.33_ 7.99_0.00_0.00_0.00^10.00:Bar_5.茰䬎愀猀猀攀渀戀蔀  賎ⰶ偱돲夙媽䡄 濢訓乂譨뱭鳖岙ਰ'#$0806'蘪칈нȃĂᜡㄍ〹ㄹㄴ㌴〷娳䜄䔰ℂ輀䇸餤腉팩㢖騝짡꾔䕯䕙폛⌹孂谯 Ɏ⨠Ꝿ玃ԣ'#$D828'屰ꊬ盭ᑏ䂥瓉짚䛄䷋彈꡵'#$ABAC#$ABAB#$ABAB#$ABAB' ﺫﻮﻮﻮ'#0#0#0#0'厁ᖟ'#0'膰'#$0092#$9FD8#$0092'ﻮﻮﻮﻮﻮﻮﻮﻮ ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ'

Vielen Dank für Eure Hilfe. Ich versuche es jetzt erstmal mit der anderen function. Mal schauen, was da raus kommt.

samso 17. Sep 2019 13:33

AW: c DLL char++ übersetzen
 
Schön, jetzt ist mir auch klar, weshalb die Kollegen sich gleich erkannt haben. Der Link auf die Headerdatei hätte ja vielleicht auch gleich in #1 stehen können. Könnte es sein, dass die Logmessage vielleicht kein Zeiger auf einen String ist, sondern eher ein Zeiger auf die "Common Log Message Structure"?

mfoerste 17. Sep 2019 13:46

AW: c DLL char++ übersetzen
 
Sorry, das habe ich nicht gewusst. In der Beschreibung stand davon kein Wort.

Zeitgleich mit diesem Thread habe ich eine Anfrage beim Hersteller gestartet.
Und fast zeitgleich erhalte ich folgende Antwort vom Hersteller:

Es handelt sich bei der LogMessage um eine ASN.1 Datenstruktur. Diese ist vom BSI (https://www.bsi.bund.de/SharedDocs/D...cationFile&v=4) Kapitel 2.1 vorgegeben.

Da wartet eine Menge Arbeit auf mich.

Vielen Dank nochmals für die tolle Unterstützung. Dieses Forum ist einfach der Hammer.:thumb:

DeddyH 17. Sep 2019 16:42

AW: c DLL char++ übersetzen
 
Wenn ich mich recht entsinne werden die LogMessages doch lediglich beim Export benötigt. Da könnte man ja auch einfach hergehen und aus PAnsiChar PByte machen, somit die Rohdaten ohne Interpretation abgreifen und in einer Datei speichern (mittels eines TStreams z.B.), und fertig ist die Laube.

Dalai 17. Sep 2019 17:18

AW: c DLL char++ übersetzen
 
Nur so zur Info: unsigned long int sollte man in Delphi nicht zu einem integer machen, sondern entweder zu einem DWORD oder Cardinal. Integer ist zwar 32 bit lang, aber mit Vorzeichen, unsigned ist aber vorzeichenlos.

Grüße
Dalai

mfoerste 18. Sep 2019 06:12

AW: c DLL char++ übersetzen
 
Zitat:

Zitat von DeddyH (Beitrag 1446679)
Wenn ich mich recht entsinne werden die LogMessages doch lediglich beim Export benötigt. Da könnte man ja auch einfach hergehen und aus PAnsiChar PByte machen, somit die Rohdaten ohne Interpretation abgreifen und in einer Datei speichern (mittels eines TStreams z.B.), und fertig ist die Laube.

Das wäre cool. Dieser TSE Kram ist echt zum :pale:

samso 18. Sep 2019 06:37

AW: c DLL char++ übersetzen
 
Ich fasse mal zusammen:

Delphi-Quellcode:
function readLogMessage(var logMessage: pByte;
                        var logMessageLength: Cardinal):Integer; stdcall; external 'fremdedll.dll';
Delphi-Quellcode:
function WriteLogToStream(Stream: TStream): Integer;
var
 msg: pByte;
 msgLength: Cardinal;
begin
  Result := readLogMessage(msg, msgLength);
  if Result = EXECUTION_OK then
    Stream.WriteBuffer(msg^, msgLength); // und hier wird dann msgLength wieder zu einem Integer. D.h. Überlauf bei 2GB ;-)
end;

mfoerste 18. Sep 2019 09:43

AW: c DLL char++ übersetzen
 
Zitat:

Zitat von samso (Beitrag 1446783)
Ich fasse mal zusammen:

Delphi-Quellcode:
function readLogMessage(var logMessage: pByte;
                        var logMessageLength: Cardinal):Integer; stdcall; external 'fremdedll.dll';
Delphi-Quellcode:
function WriteLogToStream(Stream: TStream): Integer;
var
 msg: pByte;
 msgLength: Cardinal;
begin
  Result := readLogMessage(msg, msgLength);
  if Result = EXECUTION_OK then
    Stream.WriteBuffer(msg^, msgLength); // und hier wird dann msgLength wieder zu einem Integer. D.h. Überlauf bei 2GB ;-)
end;

WOW:shock:, vielen Dank!:-D

hhcm 15. Okt 2019 14:12

AW: c DLL char++ übersetzen
 
Hallo,

ich wollte jetzt nicht den x ten Thread zur TSE Programmierung eröffnen und der Code der hier geschrieben wurde sieht schwer nach A-Trust aus :)
Bei mir sieht die ganze Sache komplett anders aus.

Delphi-Quellcode:
function TSE_readLogMessage(var logMessage: TBytes; var logMessageLength: LongWord): ShortInt; stdcall; external 'fremdedll.dll' name 'readLogMessage';

procedure SaveBytesToFile(const Data: TBytes; const Len: LongWord; const Filename: String);
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    if Data <> nil then
      Stream.WriteBuffer(Data[0], Len);
  finally
    Stream.Free;
  end;
end;

procedure ReadLogMessage(BinFilename: String);
var
  res: ShortInt;
  log: TBytes;
  len: LongWord;
begin
  log := nil;
  len := 0;

  res := TSE_readLogMessage(&log, &len);
  setLength(log, len);
  SaveBytesToFile(log, len, BinFilename);
end;
Ich bekomme da genau so einen Quark raus, wie bei dem JAVA Beispiel.
Das einzige was richtig funktioniert sind die ganzen ExportDataFilteredByxxxxx funktionen. Start und FinishTransaction war auch nicht so kritisch. Wo ich komplett auf dem Schlauch stehe sind die Rückgabewerte. Nirgens ist definiert was z.B ERROR_START_TRANSACTION_FAILED für einen Wert hat.
Es gibt ein C Beispiel mit header dateien, in diesen stehen negative Rückgabewerte für die Konstanten z.B -5001. Ich bekomme als Rückgabe entweder eine 0 oder z.B 116. Hat da jemand eine Idee?

TiGü 15. Okt 2019 15:43

AW: c DLL char++ übersetzen
 
Zitat:

Zitat von hhcm (Beitrag 1449678)
Hallo,

ich wollte jetzt nicht den x ten Thread zur TSE Programmierung eröffnen und der Code der hier geschrieben wurde sieht schwer nach A-Trust aus :)
Bei mir sieht die ganze Sache komplett anders aus.

Delphi-Quellcode:
function TSE_readLogMessage(var logMessage: TBytes; var logMessageLength: LongWord): ShortInt; stdcall; external 'fremdedll.dll' name 'readLogMessage';

...

procedure ReadLogMessage(BinFilename: String);
var
  res: ShortInt;
...
  res := TSE_readLogMessage(&log, &len);
...
end;
Es gibt ein C Beispiel mit header dateien, in diesen stehen negative Rückgabewerte für die Konstanten z.B -5001. Ich bekomme als Rückgabe entweder eine 0 oder z.B 116. Hat da jemand eine Idee?

Gehe noch mal in dich und prüfe, ob -5001 in den Wertebereich von
Delphi-Quellcode:
ShortInt
passen.
Dann überlege, ob der Typ des Rückgabewertes von TSE_readLogMessage passt.
Nur weil die Namen ähnlich sind
Delphi-Quellcode:
short int
und
Delphi-Quellcode:
ShortInt
muss es nicht zwangsläufig das selbe sein.

https://de.wikipedia.org/wiki/Datentypen_in_C
http://docwiki.embarcadero.com/RADSt...e_Integertypen

hhcm 15. Okt 2019 17:22

AW: c DLL char++ übersetzen
 
Zitat:

Nur weil die Namen ähnlich sind short int und ShortInt muss es nicht zwangsläufig das selbe sein.
:roll: Wie doof. Im Trott einfach übernommen. SmallInt wäre wohl richtiger. Dann passts auch. Danke!!!

---

Auch wenn sich "nenn wir es mal Konkurrenten" nicht immer verstehen, hat jemand lust auf einen Gedankenaustausch?
Wir haben bisher die Österreichische-RKSV über A-Trust abgewickelt, daher setzen wir auch jetzt wieder darauf, auch wenn es holprig war.
Die Entwicklerdoku bei A-Trust ist fehlerbehaftet aber ziemlich komplett.

Ich bin allerdings auch nicht festgefahren.

mfoerste 18. Okt 2019 12:12

AW: c DLL char++ übersetzen
 
Zitat:

Zitat von hhcm (Beitrag 1449678)
Hallo,

Ich bekomme da genau so einen Quark raus, wie bei dem JAVA Beispiel.

upps, falscher thread


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:21 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