Neues Thema starten
Beantwortet

Export von TAR-Dateien über die StdCall-DLL

Wir versuchen aktuell den TAR-Export mit der StdCall-DLL umzusetzen.

Leider scheitern wir noch daran. 


 Den DLL-Funktionsaufruf haben wir so deklariert: 

TWorm_export_tar = function(context: Pointer; callback: Pointer; callbackData: PAnsiString): Integer; stdcall;

 Die Callback-Funktion so:

 

TWormExportTarCallBack = function(const chunk: Pointer; const chunkLength: NativeUInt; const callBackData: PAnsiString): Integer; stdcall;

Der Aufruf der Export-Funktion erfolgt so: 

 

 worm_export_tar(context, @exportTarCallback, @callBackData)

 

Die Callback-Funktion wird auch aufgerufen, allerdings ist "chunkLength" immer 0 und als Chunk kriegen wir folgende Werte:

info.csv

Unixt_1573748718_Sig-1398_Log-Tra_No-14_Start_Client-15683-0001-0001-0001.log

Unixt_1573827489_Sig-1462_Log-Sys_LogOut.log


Hat jemand eine Idee woran das liegen kann bzw. was wir falsch machen?


Beste Antwort

Habe heute eine Rückmeldung erhalten, der Fehler konnte nachgestellt werden und ist in der nächsten SDK-Version behoben :)


Hallo!


Wir haben das folgendermaßen umgesetzt:


Funktionsköpfe:

 

WormExportTarCallback = function(chunk: PByte; chunkLength: Cardinal; callbackData: Pointer): Integer; stdcall;

function worm_export_tar(context: PWormContext; callback: WormExportTarCallback; callbackData: Pointer): WormError; stdcall;

 Den Aufruf habe ich im folgenden Code dargelegt. Bitte nicht erschrecken, dass ist noch sehr sehr quick und dirty aber es klappt :)


  

var
callbackData : pointer;
cb : WormExportTarCallback;

function  myWormExportTarCallback (chunk: PByte; chunkLength: Cardinal;
       callbackData: Pointer): Integer; stdcall ;
var
bytes : array [0..66000] of byte;
n : integer;
aExport : string;
begin
inc(ftse_dialog.iChunks);
  ftse_dialog.mExport.Lines.Add(IntToStr(ftse_dialog.iChunks)+' Lnge '+IntToStr(chunkLength));
     for n:= 0 to (chunkLength)-1
     do begin
       bytes[n] := chunk[n];
       if bytes[n] > 32  then
         aExport := aExport +  chr(bytes[n])
       else
         aExport := aExport + '#'+IntToStr(bytes[n]);
     end;
  ftse_dialog.mExport.Lines.Add(aExport);
  result := 0;
end;

procedure TfTSE_Dialog.BitBtn5Click(Sender: TObject);


begin
GetMem(callbackData, 65000);
iChunks := 0;
cb := myWormExportTarCallback;
worm_export_tar( WormAccess.pcontext ,cb ,callbackData);
lExportStatus.Caption := 'fertig';
end; 

  

Bei Fragen gerne melden!


Über Verbesserungsvorschläge freue ich mich natürlich auch! :)

 Unseres sieht in groben Zügen so aus:

 

type
  PBytes = ^TBytes;
  TOnExportBlock = function(aBlock: PBytes; aLength: DWORD; aBlock1: PBytes): Integer; stdcall; { cdecl; }

function WormExportTarCallback(aBlock: PBytes; aLength: DWORD; aUserData: PBytes): Integer; stdcall; { cdecl; }
var
  laenge: Integer;
begin
  Result := 0;
  try
    laenge := Length(aUserData^);
    SetLength(aUserData^, laenge + Integer(aLength));
    Move(aBlock^, aUserData^[laenge], aLength);
  except
    Result := 1;
  end;
end;

function TTSESwissbitConnection.GetArchivExport: TBytes;
var
  res: Integer;
begin
  Self.InitTSE;
  try
    SetLength(Result, 0);
    res := Self.W_Export_Tar(FWormContext, WormExportTarCallback, @Result);
  finally
    Self.TerminateTSE;
  end;
end;

function TTSESwissbitConnection.GetArchivExport(const aKasse: PAnsiChar; const aNummerVon, aNummerBis: UInt32): TBytes;
var
  res: Integer;
begin
  Self.InitTSE;
  try
    SetLength(Result, 0);
    res := Self.W_Export_Filtered_Transaction(FWormContext,
                                              aNummerVon,
                                              nummerBis,
                                              nil {aKasse},
                                              WormExportTarCallback,
                                              @Result)
  finally
    Self.TerminateTSE;
  end;
end;

 Wie bereits geschrieben - der gefilterte Export funktioniert nicht.

Witzigerweise ist es auch egal, ob man die Callback-Fkt. mit stdcall oder cdecl deklariert.

Wahrscheinlich funktioniert beides, da der Aufruf intern so programmiert ist, daß alle Register gesichert werden.

Das ist übrigens in WormDLL.h die einzige Stelle, die sich zur Version 5.2.3 geändert hat:

Von typedef int (*WormExportTarCallback)(const unsigned char *chunk,
                                     unsigned int chunkLength,
                                     void *callbackData);

(API V. 5.2.)
zu typedef int(WORMAPI_CALL *WormExportTarCallback)(const unsigned char *chunk,
                                                 unsigned int chunkLength,
                                                 void *callbackData);
(API V.5.2.3)
Ob sich tatsächlich intern etwas geändert hat, weiß kein Mensch...
Vlt. könntet ihr auch mal das stdcall-Demo wormGui.exe aus ..\Swissbit_TSE_API_v5.2.3\sdk\c\windows32-stdcall\bin\
ausprobieren. Bei uns kommt dort beim Auslesen nur "Grütze" raus.

MfG Henrik

Hallo Henrik,


Bei mir kommt mit der Windows - Stdcall Version ebenfalls nur Mist raus, bzw. ich bekomme eine Exception beim Klick auf eine Transaktion "Die arithmetische Operation hat einen Überlauf verursacht." Mit der Windows 32bit Version ohne stdcall klappts aber.


Wir vermuten, dass es hier aber an der Hardware liegt. Wir haben Implementierungskit I Pakete gekauft "damals". Nach Aussage von Gastro-MIS ist aber folgendes zu beachten:


"Leider können Sie die aktuelle Firmware und SDK erst mit dem zweiten Implementierungspaket verwenden. Die TSE, welche im ersten Implementierungspaket enthalten war kann nicht upgedated werden, da diese nicht die aktuelle Hardware besitzt."


Das würde heißen, das wir die neuen Funktionalitäten also insbesondere auch der gefilterte Export der laut Changelog in Version 5.1 dazugekommen ist nicht nutzen können.

Hallo Kevin,

ach du Sch... und wir haben hier tagelang probiert...
Weißt du, woran man alte und neue Version unterscheiden kann? Bei uns kam die TSE "damals" recht formlos in einem Briefumschlag an.
Wir haben mal ein paar worm_info_..Statusfunktionen aufgerufen.
Ich liste hier mal die Rückgabewerte auf. Vielleicht kannst du bei Gelegenheit mal mit den Werten eurer TSE vergleichen.
Falls ihr wirklich die erste Version habt und die Werte identisch sind, ist ja alles klar...
W_SignatureAlgorithm: ecdsa-plain-SHA384
DLL-Version: 5.2.3
Hardware Version: 1536
Software Version:  1792
Firmware Version: 1792
Is Development Firmware: 1

MfG Henrik

Hallo,


vielen Dank für eure Hilfe! Ich hab den vollständigen Export jetzt auch hin bekommen.


Die Deklaration sieht jetzt folgendermaßen aus:

 

type
  PBytes = ^TBytes;
  TWormExportTarCallBack = function(chunk: PBytes; chunkLength: Cardinal; callbackData: PBytes): Integer;stdcall;
  TWorm_export_tar = function(context: Pointer; callback: TWormExportTarCallBack; callbackData: Pointer): UInt32; stdcall;

 Und die Aufrufe jetzt so:

  

function exportTarCallback(chunk: PBytes; chunkLength: Cardinal; callbackData: PBytes): Integer; stdcall;
var
  laenge: Integer;
begin
  Result := 0;
  try
    laenge := Length(callbackData^);
    SetLength(callbackData^, laenge + Integer(chunkLength));
    Move(chunk^, callbackData^[laenge], chunkLength);
  except
    Result := 1;
  end;
end;

function TSwissbitAccess.export_tar(context: TWormContext): Integer;
var
  data: TBytes;
  fs: TFileStream;
begin
  Assert(@worm_export_tar <> nil, 'Function not found: worm_export_tar');

  SetLength(data, 0);
  Result := worm_export_tar(context, exportTarCallback, @data);

  if Length(data) > 0 then
  begin
    fs := TFileStream.Create('C:\temp\export.tar', fmCreate);
    fs.WriteBuffer(data, Length(data));
    fs.Free;
  end;
end;


Der gefilterte Export über eine Transaction-Number oder auch über die Zeit klappt nicht. Es kommt immer der Fehler  "WORM_ERROR_TSE_INVALID_PARAMETER".


Wenn ich die cdecl-Variante verwende klappt auch der gefilterte Aufruf


Das ist die Deklaration dann, die Callback-Definition ist die Selbe wie bei der StdCall-Variante (bis auf die Aufrufkonvention): 

TWorm_export_tar_filtered_transaction = function(context: Pointer; transactionNumberStart, transactionNumberEnd: UInt64;
    clientId: PAnsiChar; callback: TWormExportTarCallBack; callbackData: Pointer): Integer; cdecl;
  
TWorm_export_tar_filtered_time = function(context: Pointer; startDate, endDate: Int64; clientId: PAnsiChar;
    callback: TWormExportTarCallBack; callbackData: Pointer): Integer; cdecl;

 

Gruß,

Dennis

Hallo Dennis,
schön das es jetzt bei euch klappt. Das waren auch unsere Erfahrungen.
Nur zur Sicherheit: Bei der cdecl-Variante nimmst du auch die cdecl-DLL, oder?
Leider sind die Parameter ja nicht ganz gleich (uint32 zu uint64). Wir hatten uns schon auf stdcall festgeschossen. Falls wir das nicht mehr hinbekommen, müssen wir die Funktionen alle noch umstellen.

MfG Henrik

Hallo Henrik,

ja, dann nehme ich auch die cdecl-DLL. Vielleicht ist in der Stdcall-DLL noch ein Fehler den Swissbit noch behebt oder wir kriegen noch weitere Infos.


MfG Dennis

Hallo Henrik,


ich kann leider die Daten nicht auslesen aktuell. Implementierungskit 1 haben wir ca. Mitte des Jahres für 20€ gekauft.

Sobald ich die Daten habe, sage ich Bescheid.


MfG

Kevin

Bezüglich des Problem mit dem gefilterten Export in der stdcall Variante habe ich folgende Antwort von SwissBit bekommen:


"in der stdcall Variante sind alle in der C-Bibliothek als worm_uint deklarierten Typen 32bit, in der cdecl Variante 64bit.

Daher müssen Sie für die stdcall Varianten in Ihren Imports die kleineren Integer Typen verwenden. Dies betrifft übrigens nicht nur die Exportfunktionen, sondern alle Funktionen."


Kann damit das Problem gelöst werden?

Hallo Leute!


Meine bisherigen erfahrungen zum Export mit 5.2.3 belaufen sich auf folgendes (Implementierungskit 2):


x64-dll:

Nachdem mir aufgefallen ist, dass der maxRecords Parameter gegenüber früheren  Versionen in den beiden filtered-Funktionen verschwunden ist klappen alle drei wunderbar.


x86-stdcall - alle ulong-Parameter auf uint adaptiert bei DllImport:

- worm_export_tar: funktioniert einwandfrei

- worm_export_tar_filtered_*: WORM_ERROR_TSE_INVALID_PARAMETER


x86-cdecl - gleiche Parametertypen wie x64:

- alle drei Funktionen machen probleme




@Maximilian:
Bringt nichts - wie bereits von mir irgendwann/-wo schon einmal erwähnt, haben wir ein simples C-Programm mit stdcall gebaut, das ebenfalls nicht funktioniert. Da man dafür zwangsläufig die WormAPI.h -Header-Datei im Original einbaut, kann ich bestätigen, daß es nicht funktioniert.
Auch das bereits kompilierte! Original-Demo aus ....\c\windows32-stdcall\bin\wormGui.exe funktioniert nicht.
@Jan:
Schön, daß es bei Dir auch nicht klappt.. 8-(

Wir starten jetzt noch einmal einen Versuch über einen Ansprechpartner bei Swissbit. Der erste verlief leider enttäuschend...

MfG Henrik

 

@Henrik Die WormGUi.exe funktioniert mit stdcall leider nicht.

 Kannst du mir dein C-Programm zur Verfügung stellen, welches mit stdcall arbeitet, dann frage ich nochmals bei SwissBit nach. Ich bekomme da relativ schnell eine Antwort. 


@Jan:

Was genau funktioniert bei der 32Bit-Dll mit cdecl nicht?


Grüße

Maximilian

Bitte schön...Reicht bis morgen...8-)

Die kompilierte Exe ist mit dabei. Es ist ein Kommandozeilenprogramm mit zwei Parametern: Laufwerk und Kassenname.

Der Aufruf lautet dann z.B. so:  TSESwissbit.exe V: 4

Es wird zuerst der Komplett-Export ausgeführt - dieser funktioniert. Die Daten werden nicht gespeichert.

Danach wird der gefilterte Export nach Transakt.-Nr. ausgeführt - dieser scheppert mit dem bekannten Fehler.

Die Aufrufparameter (Transakt.Nr./Kassenname) kann man leicht ändern.

getestet mit:

- SDK 5.2.3

- MS Visual Studio 2015 (höhere Versionen funktionieren ebenfalls; andere Compiler sollten ebenfalls funktionieren - das Bsp. ist simpel)

- stdcall

- lib-Datei zum Linken steckt mit im WormAPI-Header-Verzeichnis

  Falls du es mit VS versuchst, mußt du die Projekt-Pfade anpassen (u.a. für die Import-Library)


MfG Henrik


zip
Anmelden oder Registrieren um einen Kommentar zu veröffentlichen