Seite 1 von 2

TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Do, 05. Mär 2020 18:01
von miwe-pos
In den Funktionen von Swissbit-TSE in der wormApi.dll werden an mancher Stelle Pointer verlangt. Beisp.:
worm_info_tseSerialNumber ( const WormInfo * info, const unsigned char ** serialNumber, worm_uint * ;
serialNumberLength )
Das Problem ist der char** -Pointer für die Seriennummer. Ich habe schon vieles versucht. Ich rufe die Funktion über EXTERN auf
EXTERN CDECL worm_info_tseSerialNumber(info AS INTEGER64, @serialNumber AS INTEGER64 , serialNumberLength as integer );
in WormAPI.dll // habe es auch mit @serialNumber AS String versucht.
Hier der eigentliche Funktionsaufruf:
local serialnumber:=space(32) //sie ist 32 Byte lang
local nsernumberlng, npointer, sernrLng
npointer:=_pgrab(serialnumber, @sernrLng) //CHARPointer aus ot4xb
//npointer ist eine Zah und sernrLng ist 32+1
xvar:= worm_info_tseSerialNumber(info, @npointer, nsernumberlng ) //info ist vorher durch info_new() und info_read()
//initialisiert und funktioniert bei anderen Info-Funktionen
ERgebnis Programmabsturz mit folgenden Fehlern:Internal data structures corrupted, :gencode 41:subcode5
VALTYPE: C VALUE: _DLL
-> VALTYPE: N VALUE: 6426768 //der Wert von info
//wird der Pointer mit Referenz als Integer64 oder String übergeben dann
->Valtype: N 32
//-> VALTYPE: N VALUE: 1934375456 //Pointerwert bei Übergabe ohne Referenz
-> VALTYPE: N VALUE: 32 //Seriennummernlänge
Ich weiß nicht mehr weiter! Hat jemand eine Idee? An diesem Problem könnte mein TSE-Einbindung scheitern!
aus allgemeine Fragen hat geschrieben: TSE-Kasse Pointer in C-Funktionen Swissbit
#1 Beitrag von miwe-pos » Do, 05. Mär 2020 23:53

In den Funktionen von Swissbit-TSE in der wormApi.dll werden an mancher Stelle Pointer verlangt. Beisp.:
worm_info_tseSerialNumber ( const WormInfo * info, const unsigned char ** serialNumber, worm_uint * ;
serialNumberLength )
Das Problem ist der char** -Pointer für die Seriennummer. Ich habe schon vieles versucht. Ich rufe die Funktion über EXTERN auf
EXTERN CDECL worm_info_tseSerialNumber(info AS INTEGER64, @serialNumber AS INTEGER64 , serialNumberLength as integer );
in WormAPI.dll // habe es auch mit @serialNumber AS String versucht.
Hier der eigentliche Funktionsaufruf:
local serialnumber:=space(32) //sie ist 32 Byte lang
local nsernumberlng, npointer, sernrLng
npointer:=_pgrab(serialnumber, @sernrLng) //CHARPointer aus ot4xb
//npointer ist eine Zah und sernrLng ist 32+1
xvar:= worm_info_tseSerialNumber(info, @npointer, nsernumberlng ) //info ist vorher durch info_new() und info_read()
//initialisiert und funktioniert bei anderen Info-Funktionen
ERgebnis Programmabsturz mit folgenden Fehlern:Internal data structures corrupted, :gencode 41:subcode5
VALTYPE: C VALUE: _DLL
-> VALTYPE: N VALUE: 6426768 //der Wert von info
//wird der Pointer mit Referenz als Integer64 oder String übergeben dann
->Valtype: N 32
//-> VALTYPE: N VALUE: 1934375456 //Pointerwert bei Übergabe ohne Referenz
-> VALTYPE: N VALUE: 32 //Seriennummernlänge
Ich weiß nicht mehr weiter! Hat jemand eine Idee? An diesem Problem könnte mein TSE-Einbindung scheitern!
Nach oben

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Fr, 06. Mär 2020 6:00
von AUGE_OHR
hi,
miwe-pos hat geschrieben: Do, 05. Mär 2020 18:01 In den Funktionen von Swissbit-TSE in der wormApi.dll werden an mancher Stelle Pointer verlangt. Beisp.:
worm_info_tseSerialNumber ( const WormInfo * info, const unsigned char ** serialNumber, worm_uint * ;
serialNumberLength )

Hier der eigentliche Funktionsaufruf:
local serialnumber:=space(32) //sie ist 32 Byte lang
local nsernumberlng, npointer, sernrLng

npointer:=_pgrab(serialnumber, @sernrLng) //CHARPointer aus ot4xb
//npointer ist eine Zah und sernrLng ist 32+1
xvar:= worm_info_tseSerialNumber(info, @npointer, nsernumberlng ) //info ist vorher durch info_new() und
die Ot4xb Syntax ist falsch

Code: Alles auswählen

@ DLL-Name:Function()

@user32:DestroyIcon( ::Handle )
ich halte "WormInfo" für eine Structure. es müsste eine API Beschreibung geben (meisten in *.H Dateien)

Code: Alles auswählen

BEGIN STRUCTURE WormInfo
   MEMBER LPSTR serialNumber
   MEMBER DWORD cbSize
END STRUCTURE
einen genügend grossen leeren String, mit CHR(0) am Ende, übergibt man per Referenz.

Code: Alles auswählen

#include "OT4XB.CH "

LOCAL oWI := WormInfo():New()
LOCAL cSN := SPACE(32)+CHR(0)

   @wormApi:worm_info_tseSerialNumber(oWI, @cSN, 32)
---

es ist ja ein xBase Forum und da gibt es nicht viele die sich mit API oder C beschäftigen.

p.s. wormApi.dll ist eine 32 Bit DLL :?:

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Fr, 06. Mär 2020 7:23
von brandelh
char müsste ein 8 bit string sein, keinesfalls eine Integer.
CONST ist eine Konstante, also kein @ Zeichen in Xbase++ übergeben

Wenn es ein String ist, sollte es genügen einfach die Stringvariable als solche oder den String als Parameter anzugeben ...

in der Hilfe zu EXTERN ist unten bei [@] ... TYPE die Liste der möglichen TYPEN der Parameterbeschreibung angegeben, ähnlich der bei der Rückgabe type der DLL (immer die richtige Tabelle nehmen):

Code: Alles auswählen

[@] <Parameter> AS <Type> 

Specifies the name and the data type of the parameters passed to the DLL function. The data type of the parameters expected by the DLL function must be specified following the keyword AS using one of the following key words. 

Parameter types of DLL functions 
Key word	Description		 	Corresponding C/SDK types (examples) 
SHORT		16 bit integer	 		SHORT, short int 
USHORT		Unsigned 16 bit integer		USHORT, unsigned short 
INTEGER		32 bit integer 			BOOL, int 
LONG 		32 bit integer 			INT32 
UINTEGER 	Unsigned 32 bit integer		DWORD, LPDWORD, LPARAM, PVOID, HANDLE, HWND, UINT, ULONG 
INTEGER64 	64 bit integer 			INT64 
UINTEGER64 	Unsigned 64 bit integer		UINT64, ULONG64, DWORD64 
SINGLE		32 bit floating point 		FLOAT32, float 
DOUBLE 		64 bit floating point 		FLOAT64 
STRING 		Character string 		LPSTR, PSZ, char, char* 
IDISPATCH 	COM/ActiveX object (IDispatch) 	IDispatch* 
CALLBACK 	Callback function 		WNDENUMPROC, DLGPROC 
CALLBACKA 	Asynchronous callback function 	WNDPROC, HOOKPROC 
XPPVALUE 	An arbitrary Xbase++ value (not applicable) 
Das ist dein Typ und ohne @ da keine Rückgabe erwartet wird:

STRING Character string Für Xbase Extern !!! ist das alles das Gleiche: LPSTR, PSZ, char, char*

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Fr, 06. Mär 2020 7:25
von Jan
Ein wenig OT: ich denke, diese Diskussion gehört nicht in die Wissensbasis. Die Wissensbasis ist das Teilen von Wissen und Erkenntnissen mit den anderen Entwicklern., Aber nicht Problem-Diskussionen.

Jan

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Fr, 06. Mär 2020 7:41
von brandelh
Stimmt, keine Wissensbasis ... 3 Einträge über dieser Nachricht habe ich die Parameter von Extern erklärt, wenn man die Hilfe liest und weiß um was es in API / C Dlls geht, sollte das kein Problem sein.

Die gleiche Anfrage unter Allgemein lösche ich und dieses Thema habe ich unter Windows API (ist auch C-DLL von fremden Herstellern gemeint) verschoben.

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Sa, 07. Mär 2020 4:43
von AUGE_OHR
hi,

Xbase v2.x scheint was DLL angeht ja einiges gelernt zu haben =D>
wie sieht es mit Structure aus, wird BAP noch benötigt :?:

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Sa, 07. Mär 2020 19:06
von miwe-pos
Zuerst einmal lieber Brandelh, gehe bitte davon aus, dass ich die Anleitungen zu Extern gelesen habe; ob ich sie verstanden habe, ist eine andere Frage. Dass XBASE ++ nicht aus einem Guss ist, dazu gleich ein Beispiel:
EXTERN STDCALL worm_tse_runSelfTest(WormContext AS INTEGER64, clientid AS STRING) in WormAPI.dll //dazu der Aufruf
xvar:=worm_tse_runSelfTest(WormContext, clientID)
Ergebnis Programmabsturz oError:args :
-> VALTYPE: C VALUE: _DLL ÝpFÝ
-> VALTYPE: N VALUE: 1536760 //wormcontext
-> VALTYPE: C VALUE: 4711 //ClientID
oError:description : Internal data structures corrupted
oError:genCode : 41
oError:operation : dllExecuteCall
oError:severity : 2
oError:subCode : 5
Nun der Programmaufruf mit dllcall mit den gleichen Werten:
xvar:=dllcall("wormapi.dll",DLL_STDCALL,"worm_tse_runSelfTest", Wormcontext,clientID)
Kein Programmabsturz - xvar=0 d.h. erfolgreich ausgeführt!!

Nun zum eigentlichen Problem - Zeiger - zuerst Aufruf mit EXTERN
EXTERN STDCALL worm_info_tseSerialNumber(info AS INTEGER64,@serialNumber AS STRING ,;@serialNumberLength as integer );
in WormAPI.dll
xvar:= worm_info_tseSerialNumber(info,@TSESERNUMBER,@sernrlng )
Ergebnis Programmabsturz oError:args :
-> VALTYPE: C VALUE: _DLL ç :ç
-> VALTYPE: N VALUE: 1539744 //Worminfo ein Pointer der von worm_info_new zurückgegeben wird
-> VALTYPE: C VALUE: 32Leerzeichen
-> VALTYPE: N VALUE: 32
oError:description : Internal data structures corrupted
oError:genCode : 41
oError:operation : dllExecuteCall
oError:severity : 2
oError:subCode : 5

Nun der Aufruf über dllcall:
xvar:=dllcall("wormapi.dll",DLL_STDCALL,"worm_info_tseSerialNumber",info,@TSESERNUMBER,@sernrlng )

Kein Absturz! Rückgabe: xvar=268999696 und TSESERNUMBER binär 58 5F 17 00 und dann 28x die 20 für Leerzeichen!
Das scheint zuerst einmal schön zu sein doch leider völlig falsch! Da war ich schon vor 3 Wochen. Die richtige Seriennummer müsste so
lauten:"f884917c6f18938adf2b299eb45bae5f94e0dd7ecd5f6fa77a15cb042d83f61b"

Fazit: Mit Werteübergabe per Referenz habe ich nicht den char**-Pointer der benötigt wird. Und Jan es geht mir sehr wohl um Wissensbasis.
Das ist ein Problem der Einbindung der Swissbit-TSE. Auch wenn ich mich erst vor Kurzen neu angemeldet habe, meine Anmeldedaten von Anfang der 2000-er habe ich verschlampt, war damals Mitglied der Berliner/Brandenburger Gruppe, bin ich mit fast 76 kein "grüner Junge". Habe seit
Anfang der 80-er Jahre programmiert (BASIC,DBASE,TurboPascal, C auf DOS-Basis und dann durch Arbeitsplatzwechsel ab 1991 Clipper und daher als Folge XBASE++. War mein Fehler solange nicht im Forum gewesen zu sein. Hab vielleicht dadurch an manchen Stellen das "Fahrrad" zum zweiten Mal erfinden müssen.
Es geht um das Problem TSE in Kasse unter XBASE++ einzubinden!!! Offensichtlich ist damit noch keiner im Forum fertig!!
Vielleicht finden wir gemeinsam eine Lösung??
Beste Grüße an Alle

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Sa, 07. Mär 2020 19:09
von miwe-pos
Hallo Jimmy,
Deine Frage hab ich fast vergessen.
Anscheinend Ja, da die Pointer-Frage noch nicht geklärt ist.

GRuß
Michael

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Sa, 07. Mär 2020 22:36
von AUGE_OHR
hi,
miwe-pos hat geschrieben: Sa, 07. Mär 2020 19:09 Deine Frage hab ich fast vergessen.
Anscheinend Ja, da die Pointer-Frage noch nicht geklärt ist.
bist du dir sicher das es sich um eine 32 Bt DLL handelt :?:
diese kleine v1.9.355 App kann das feststellen
dll6432.zip
for Xbase++ v1.9.355
(3.1 KiB) 373-mal heruntergeladen

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: So, 08. Mär 2020 10:23
von miwe-pos
Hallo Jimmy,

Die Doku von Swissbit ist auch nicht so erhellend.
Ich habe die API aus dem Verzeichnis \swissbit\sdk\c\windows32-stdcall\bin genommen 41.984 Byte lang. Dort sind auch die
Testprogramme WormCli.exe und WormGui.exe. Im Verzeichnis ..\c\windows32\bin ist sie 37.888 Byte lang.
Beide habe ich ausprobiert die Letztere mit Aufrufkonvention CDECL. Die allgemeinen Funktionen haben mit dllcall() bei beiden
funktioniert. Nur nicht die mit char**-Pointer als Übergabeparameter.
Die 64-er DLL hat eine Länge von 45.056 Byte; ich habe sie nie probiert! Alle haben das Erstellungsdatum 04.02.2020.
Wenn es Dich interessiert, kann ich Dir das ganze SDK gepackt zusenden.

Gruß
Michael

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: So, 08. Mär 2020 22:37
von AUGE_OHR
hi,

wenn es ein 32 und 64 Bit Verzeichniss gibt dann sollte man die 32 Bit erwischen.
schon mal mit was anderem als CDECL wie DLL_OSAPI versucht :idea:

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mo, 09. Mär 2020 6:41
von brandelh
miwe-pos hat geschrieben: Sa, 07. Mär 2020 19:06 Zuerst einmal lieber Brandelh, gehe bitte davon aus, dass ich die Anleitungen zu Extern gelesen habe; ob ich sie verstanden habe, ist eine andere Frage.
wenn ich davon ausgehe dass jemand die Anleitung gelesen hat, bin ich in den meisten Fällen auf dem falschen Dampfer. 8)

DLLCALL() Aufrufe sind der altmodische Vorgänger von EXTERN und können nicht verwendet werden wenn man komplexere Datentypen als Rückgabe will. (wobei ich die 1.90 im Kopf habe, muss ich mal bei 2.00 lesen ;-) )
DLLCALL() gibt immer nur einen LONG Wert zurück.
miwe-pos hat geschrieben: Sa, 07. Mär 2020 19:06 Fazit: Mit Werteübergabe per Referenz habe ich nicht den char**-Pointer der benötigt wird. Und Jan es geht mir sehr wohl um Wissensbasis.
Das ist ein Problem der Einbindung der Swissbit-TSE. ...
Es geht um das Problem TSE in Kasse unter XBASE++ einzubinden!!! Offensichtlich ist damit noch keiner im Forum fertig!!
Vielleicht finden wir gemeinsam eine Lösung??
Das ist das was Jan meinte, die fertige Lösung gehört in die Wissensbasis, die Irrwege und Fragen dazu nicht ;-)
Xbase 2.0 Anleitung hat geschrieben:DllCall()
Calls a DLL function dynamically at runtime.

The function is deprecated. Use the EXTERN command instead.

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mo, 09. Mär 2020 7:03
von brandelh
Ich kenne diese DLL nicht, daher kann ich nur allgemein meinen Senf dazu geben:

Xbase unterstützt ausschließlich 32 Bit Versionen von DLLs.
EXTERN STDCALL worm_tse_runSelfTest(WormContext AS INTEGER64, clientid AS STRING) in WormAPI.dll
EXTERN CDECL worm_info_tseSerialNumber(info AS INTEGER64, @serialNumber AS INTEGER64 , serialNumberLength as integer ) in WormAPI.dll // habe es auch mit @serialNumber AS String versucht.
Ich habe die API aus dem Verzeichnis \swissbit\sdk\c\windows32-stdcall\bin *** wenn die DLL auch daraus ist, muss es STDCALL sein !
Zunächst muss bei Xbase++ immer geklärt werden, ob es eine DLL mit STDCALL (wohl alle API Funktionen) oder CDECL (wohl viele C-DLLs ...) ist !
Wenn man hier einen Fehler macht, werden die Parameter falsch eingelesen, was häufig mit einem FATAL ERR belohnt wird, es kann aber auch zu unerwünschten Ergebnissen kommen.
Bei Pablos OT4XB muss man das nicht angeben, er ermittelt den richtigen Typ. Ich habe nur mit seiner Klasse Erfahrungen damit.

Ich vermisse bei der EXTERN Angabe den TYP der Rückgabe der DLL Funktion.

@serialNumber AS String

wenn man hier einen @ angibt, dann nur wenn die DLL hier eine Rückgabe reinstellen soll.
wenn serialNumber ein String enthält, der gefüllt werden soll, muss die String-Variable vorher genügend groß sein, z.B. mit serialNumber := space(256) oder Replicate(chr(0), 15) ...
einfache API Funktionen liefern in diesen Fällen den String in dem per Referenz übergebenen String das Ergebnis zurück, z.B. das hier:

Code: Alles auswählen

nErr := FindExecutableA( cFile, cPath, @cExe )
if nErr > 32 // MSDN: Returns a value greater than 32 if successful, or a value less than or equal to 32 representing an error.
...
DLLFUNCTION FindExecutableA(cFile, cPath, @cEXE ) USING STDCALL FROM SHELL32.DLL
*** API Beschreibung für C++
HINSTANCE FindExecutableA(
  LPCSTR lpFile,
  LPCSTR lpDirectory,
  LPSTR  lpResult
);
Bei deiner DLL vermute ich aber eher, dass das Ergebnis in einer Struktur gefordert und geliefert wird, das macht die Sache komplexer.

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mo, 09. Mär 2020 8:51
von brandelh
Frage, in welchen Programmiersprachen liegen Beispiele bei ?

Hier dein Code Beispiel einer Funktion:

Code: Alles auswählen

worm_info_tseSerialNumber ( const WormInfo * info, const unsigned char ** serialNumber, worm_uint * serialNumberLength )
ich habe mal nachgelesen um sicher zu gehen, was "unsigned char" bedeutet, in QuickPDF gab es immer nur w_char_t *, ich bin auch schon älter und hab vieles vergessen 8)
Wickipedia zu C-Datentypen hat geschrieben:Ein Character repräsentiert die kleinste adressierbare Einheit in C, in der Regel acht Bit.
... Je nach Compiler kann char entweder gleichbedeutend sein mit signed char (-128 bis 127, fast immer der Fall) oder mit unsigned char (0 bis 255).
Beim Extern Befehl und in der Doku zur QuickPDF habe ich keinen Parameter mit ** gefunden, immer nur max 1 * , (z.B. wchar_t* filename, hier muss man die ANSI Funktion aufrufen) ...
aber in LibXL (für die ich auch einen Wrapper geschrieben habe, den kann man hier auch herunter laden):
LibXL Doku C-Beschreibung hat geschrieben: bool saveRaw(const char** data, unsigned* size)
Saves a file to internal memory buffer. Parameters:
data - pointer to buffer;
size - pointer to saved size.
Returns false if error occurs. Get error info with Book::errorMessage().
Hier meine Umsetzung in XBase 1.90ff mit OT4XB, mit Hilfe von Pablo ;-)

Code: Alles auswählen

*--------------------------------------------------------------------------------
METHOD xlBook:BookSaveRaw(bData, nSize) // call BookSaveRaw( @cData, @nSize) 
   local uRet := nil, p := 0     
   nSize := 0                    
   uRet := FpQCall( {'LibXL','xlBookSaveRawA'},'__bo__sl_@sl_@ul',::hHandle,@p,@nSize ) 
   if uRet  .and. ! empty(p)     
      bData := PeekStr(p,,nSize) 
      nSize := len(bData)        
   endif                         
RETURN uRet                      
In Xbase aufrufen mit ... o:BookSaveRaw( @cData, @nSize)

uRet := FpQCall( {'LibXL','xlBookSaveRawA'},'__bo__sl_@sl_@ul',::hHandle,@p,@nSize )

dieser ot4xb Funktion kann man genau mitgeben, wie sie was zu behandeln hat, im String-Parameter ('__bo__sl_@sl_@ul'):
Die Aufrufekonvention ermittelt die Funktion selbst.

{'LibXL','xlBookSaveRawA'}, Array mit Name der DLL und Name der Funktion, immer ANSI Version nutzen, wenn es zwei gibt.

__bo = der erste Parameter ist der RückgabeTYP der Funktion, die weiteren beschreiben die TYPen der Parameter, hier wandelt ot4xb die Rückgabe 0 zu .f. und <> 0 to .t.
__sl = signed LONG Variable, unveränderbar, hier für den DLL Handle (::hHandle)
_@sl = signed LONG Variable, erhält den neuen Wert zurück, muss daher aus Xbase++ heraus auch mit @ aufgerufen werden (@p)
_@ul = unsigned LONG Variable, erhält den neuen Wert zurück, hier die Länge der Daten in bData', (@nSize )

Um die Daten aus dem Buffer zu bekommen dient dann die Funktion PeekStr() aus OT4XB ...

Wenn man das alles in eine eigene Klasse kapselt kann man den Aufruf von Xbase++ heraus einfach halten.
Ich selbst werden meine Klassen nicht mehr auf EXTERN umschreiben, die funktionieren gut wie sie sind und ich mag diese Funktion :-)

Keinesfalls sollte man alles mischen.

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mo, 09. Mär 2020 9:12
von Martin Altmann
Hubert,
zu Deiner impliziten "Frage":
* bedeutet bei den Parametern Pointer
** bedeutet dementsprechend Pointer auf Pointer.
Mit letzterem hat(te) Xbase++ schon immer Probleme (= ging nicht). Ob sich das bei neueren Versionen geändert hat, weiß ich nicht.

Viele Grüße,
Martin

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mo, 09. Mär 2020 9:23
von brandelh
stimmt, so war das ... ich sag ja vergessen 8)

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Di, 10. Mär 2020 4:17
von AUGE_OHR
hi,
brandelh hat geschrieben: Mo, 09. Mär 2020 7:03 Zunächst muss bei Xbase++ immer geklärt werden, ob es eine DLL mit STDCALL (wohl alle API Funktionen) oder CDECL (wohl viele C-DLLs ...) ist !
aus c:\ALASKA\XPPW32\Include\dll.ch

Code: Alles auswählen

// Konstanten der Aufrufkonventionen
#define  DLL_SYSTEM               4
#define  DLL_CDECL                8
#define  DLL_STDCALL             32
#define  DLL_XPPCALL            128
#ifdef   __OS2__
  #define DLL_OSAPI             DLL_SYSTEM
#else
  #define DLL_OSAPI             DLL_STDCALL
#endif
deshalb kam ich auf DLL_OSAPI was auch "andere" xBase-Dialekte verstehen
brandelh hat geschrieben: Bei deiner DLL vermute ich aber eher, dass das Ergebnis in einer Struktur gefordert und geliefert wird, das macht die Sache komplexer.
es handelt sich doch um ein "Sicherheits-Modul", oder :?:
es wäre schon verwunderlich wenn es "Hard-Codiert" in eine Datei steckt ...

es gibt am Anfang

Code: Alles auswählen

WormInfo * info
wie Hubert vermute ich dahinter eine Windows Strukture und eine eigene scheint man ohne BAP mit Xbase++ 2.x nicht erstellen zu können.

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Di, 10. Mär 2020 8:08
von brandelh
Jimmy,

selbst ich werfe den OS/2 betreffenden Code in meinen PRG raus, daher nehme ich direkt den Wert für die Windows API ;-)

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Di, 10. Mär 2020 19:00
von miwe-pos
Der Hinweis auf ot4xb gibt mir neue Möglichketen. Überall, wo Funktionen Zahlenwerte zurück geben,geht
@wormapi:<funktion>(parameter) sehr gut und ist eine Erleichterung beim Programmieren.
Doch was ist zu tun, wenn ein String als Rückgabe erwartet wird?

Die Sache mit dem Pointer char** konnte ich auch mit ot4xb noch nicht lösen. So ganz verstehe ich das Beispiel von
Brandelh nicht. Vielleicht könnte er mir mal die ganze Beispiel-Klasse zukommen lassen.

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Di, 10. Mär 2020 21:24
von brandelh
alle meine Quellcodes stehen jedem in der Wissensbasis zur Verfügung und auf meiner Homepage.

Das Beispiel stammt von HBLibXL :arrow: viewtopic.php?f=16&t=7610&p=84578

im Quellcode wird der Pointer auf den Pointer durch die Peekstr() Funktion aufgelöst wird. Das ist eine OT4XB Funktion.

Code: Alles auswählen

if uRet  .and. ! empty(p)     
      bData := PeekStr(p,,nSize) 
      nSize := len(bData)        
endif
in dem Beispiel handelt es sich um binär Daten.

Die von vielen geliebte @ Syntax spart Schreibarbeit und es sieht der API sehr ähnlich,
Ich ziehe jedoch die von mir verwendete Funktion vor, da ich hier den Rückgabewert direkt bestimmen kann.
Pablos Klasse biegt dann die Rückgabewerte auf Xbase++ Format um oder man setzt diese in einer eigenen Funktion um ...
das mache ich z.b. wenn eine API logisch meldet, dann ist 0 zu .f. und <> 0 wird zu .t.

Braucht man für diese Worm API eigentlich die Hardware ?

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mi, 11. Mär 2020 12:40
von miwe-pos
Hallo Hubert,
zuerst mal danke! Muß ich noch ausprobieren.
Für die wormapi gibt es einige wenige Funktionen mit Aufruf "void", die ohne die Hardware auskommen.
Ansonsten braucht man die Hardware. Ich habe den Entwickler-USB-Stick, der aber auch nur bis Ende Juli nutzbar ist.
Für die TSE der Bundesdruckerei kann man bei Jarltech eine MicroSD für Entwickler 40Tage leihweise erhalten.
Das ist dann die se-api-c-stdcall.dll oder se-api-c.dll.

Gruß
Michael

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mi, 11. Mär 2020 19:17
von miwe-pos
Hallo an Alle,
ich habe es fast geschafft!

TSESERNUMBER:=space(32)
TSESERNUMBER:=_xGrab((TSESERNUMBER), @sernrlng)
xvar:=dllcall("wormapi.dll",DLL_STDCALL,;
"worm_info_tseSerialNumber",info,@TSESERNUMBER,@sernrlng )
//TSESERNUMMER gibt anscheinend wieder einen Pointer zurück
TSESERNUMBER:=PeekStr(TSESERNUMBER,,32) // Pointer to String
//String ist allerdings nicht 32 Byte sondern 160 Byte lang allerdings die letzten 32 Byte
//sind exakt die Seriennummer!!!
strfile(TSESERNUMBER,"TSESERNUM",.t.)
Ich probiere weiter, hoffe das Ergebnis noch zu verfeinern?!
Gruß
Michael

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Mi, 11. Mär 2020 19:26
von miwe-pos
Kurze Korrektur!
beim zweiten Test war der String exakt 32 Byte lang mit der exakten Seriennummer!!
Anscheinend war, da strfile(,,.t.), noch ein alter String vorher abgespeicht worden.
Damit die Pointer to Pointer (char**) - Frage gelöst!

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Fr, 19. Jun 2020 9:49
von Udo
Hallo!

Gestern habe ich kurz die Swissbit TSE API von Alaska überflogen. Da scheint Alaska eine Menge Arbeit investiert zu haben. Wenn das so funktioniert wie es da steht, kann man sich bei Alaska nur bedanken. Hat das schon mal jemand mit dem Swissbit USB Stick getestet ?

Glück Auf!
Udo

Re: TSE-Kasse Pointer in C-Funktionen Swissbit

Verfasst: Fr, 03. Jul 2020 18:33
von miwe-pos
Hallo an alle,
Habe mein TSE-Programm Version Swissbit einschließlich aller Transaktionen mit Ausnahme der "worm_export_tar..-Funktionen fertig.
Diese Funktionen benötigen einen Zeiger(Pointer) auf eine WormExportTarCallback-Funktion.
Habe dafür eine solche geschrieben und in eine externe DLL gepackt:
function WormExportTarCallback(block,blocklen,data)
static nhandle:=0
local nwrite:=0
if nhandle=0
nhandle:=fcreate((data),0)
endif
if nhandle=-1
return 1
endif
nwrite:=fwrite(nhandle,block,blocklen)
if nwrite=blocklen
return 0
else
return -1
endif
return 0
// die Funktion testweise mit dllcall(...) aufgerufen funktioniert und legt eien Datei "TAREXPOR" an!!

Im Programm habe ich folgenten Code:
local block:=space(1024), blocklen:=1024, data:="TAREXPOR",nhandle,ctext,callback
nhandle:=DLLLoad("wmcall.dll") //laden der eignen Dll ->51838976
ctext:=DLLPrepareCall(nhandle,DLL_XPPCALL,"WormExportTarCallback")
callback:=nFpCall((ctext),block,siglng,data) // //Pointer auf Funktion -> Rückgabe: 1614283112
xvar:=dllcall("wormapi.dll",DLL_STDCALL, "worm_export_tar" , WormContext, callback , data ) //Absturz
//Fehler:
oError:args :
-> VALTYPE: C VALUE: _DLL Ö ]Ö
-> VALTYPE: N VALUE: 1456568 //wormContext
-> VALTYPE: N VALUE: 1614283112 //Pointer
-> VALTYPE: C VALUE: Tarexpor //data
oError:canDefault : N
oError:canRetry : N
oError:canSubstitute: Y
oError:cargo : NIL
oError:description : Internal data structures corrupted

Hat jemand eine Idee?

Beste Grüße
Michael (miwe-pos)