/ Forside / Teknologi / Udvikling / Delphi/Pascal / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Delphi/Pascal
#NavnPoint
oldwiking 603
jrossing 525
rpje 520
EXTERMINA.. 500
gandalf 460
gubi 270
DJ_Puden 250
PARKENSS 230
technet 210
10  jdjespers.. 200
Kommunikation med C++
Fra : Michael Vilhelmsen


Dato : 23-11-07 14:07

Hej

Jeg har lavet en function, som kaldes fra en DLL, som er skrevet i C.
functionen er skrevet i Delphi.

Det eneste jeg ved om, hvordan funktionen skal være i Delphi er dette:

5.4.19 The checkStopList call-back function
Synopsis
int pcbStopList (char *Code);

Description
This callback must be activated if offline transactions are performed (merchant initiative = 0x60). The
function is called repeatedly until it returns 1 indicating that the code is ready. The callback must
deliver the 6 character authorization code issued by PBS. A timer will requires this call back function to
return 1 within 600 seconds. Best practice is to require the transaction authorization code before the
transaction is started. E.g. for ‘Dankort’ transactions this is usually done by calling PBS with merchant
id, card number and other required information, and receiving the authorization code. If a business
decision is done, that no code is required, the ECR may return 6 spaces (0x20).
The returned code is printed on the receipt as ‘AUT KODE:’

Return value 0 – code not ready yet.
1 – code ready


I Delphi har jeg så lavet følgende funtion:

function OfflineAutoCode (var RetAutCode : PChar) : Integer; SafeCall;
var
lStr : String;
begin //OfflineAutoCode
lStr := '123456';
try
frmMain.lblInfo.Caption := lStr;
if (lStr='¥¥¥¥¥¥') then
begin
Result := 0;
end
else
begin
RetAutCode := PWideChar(lStr);
Result := 1;
end;
except
RetAutCode := '';
Result := 0;
end;
end;


Dette skulle ende op med, at jeg får udskrevet noget på en skærm.
Dette skulle jo gerne være 123456 men ender op med 13 (4 blanke bagved).


Jeg ved at resultværdien (0 eller 1) virker, for der sker intet, før jeg har result=1.
Men overførselen af parametren driller mig.

Hjælp ...

Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



 
 
Michael Vilhelmsen (26-11-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 26-11-07 11:06

Bedste resultat indtil nu er med:

function OfflineAutoCode (var RetAutCode : PWideChar) : Integer; SafeCall;
var
lStr : String;
lInt : Integer;
begin //OfflineAutoCode
lStr := '123456';
FillChar(RetAutCode,SizeOf(RetAutCode),#0);

frmMain.lblInfo.Caption := lStr;
if (lStr='¥¥¥¥¥¥') then
begin
lStr := lStr + lStr;
RetAutCode := PWideChar(lSTr);
Result := 0;
end
else
begin
lStr := lStr + lStr;
RetAutCode := PWideChar(lSTr);
Result := 1;
end;
end;



Jeg burde sende 123456 over, og forvente at det bliver skrevet "i den anden ene".

Men hvis jeg sender det "to gange" som '123456123456' kan jeg se, at resultatet er:

135135

Altså hvert andet tegn.

Hvorfor lige det ?

Michaek

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Uffe Kousgaard (26-11-2007)
Kommentar
Fra : Uffe Kousgaard


Dato : 26-11-07 13:21

>
> Hvorfor lige det ?

Måske pga. denne linie:

RetAutCode := PWideChar(lSTr);

Du konverterer fra en alm. string til en unicode char. Mente du en
widestring?



Michael Vilhelmsen (26-11-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 26-11-07 13:33

Uffe Kousgaard submitted this idea :
>>
>> Hvorfor lige det ?
>
> Måske pga. denne linie:
>
> RetAutCode := PWideChar(lSTr);
>
> Du konverterer fra en alm. string til en unicode char. Mente du en widestring?


Ja, jeg mente widestring.

Det som jeg skal overføre til DLLen (og som er i C) skal afleveres som 0 termineret string, hvor hver "char" er 16 bits lang.

Det må være en PWideChar i stedet for PChar, ikke ?


Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Uffe Kousgaard (26-11-2007)
Kommentar
Fra : Uffe Kousgaard


Dato : 26-11-07 14:04

"Michael Vilhelmsen"
<Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> wrote in message
news:mn.d32c7d7b59177587.11460@Microcom.PLEASEREMOVE.Dk...
>
> Det må være en PWideChar i stedet for PChar, ikke ?

Nok nærmer en PWideString, men det er ikke et område jeg har arbejdet meget
med.



Michael Vilhelmsen (26-11-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 26-11-07 14:44

Uffe Kousgaard used his keyboard to write :
> "Michael Vilhelmsen" <Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> wrote in message news:mn.d32c7d7b59177587.11460@Microcom.PLEASEREMOVE.Dk...
>>
>> Det må være en PWideChar i stedet for PChar, ikke ?
>
> Nok nærmer en PWideString, men det er ikke et område jeg har arbejdet meget med.

Jeg har sådan set fået det til at virke nu.
Men jeg ved ikke hvorfor.


Jeg har lige prøvet med en widestring, som du sagde.
Det kom der ikke noget brugbart ud af.


Til gengæld virker dette:

function OfflineAutoCode (var RetAutCode : PWideChar) : Integer; SafeCall;
var
lStr : String;
lInt : Integer;
l2 : String;
i : Integer;
begin //OfflineAutoCode
lStr := frmMain.LaesKommPFil(KommPOfflineAutCode,6); //Læser 6 tegn.
FillChar(RetAutCode,SizeOf(RetAutCode),#0);
try
frmMain.lblInfo.Caption := lStr;
if (lStr='¥¥¥¥¥¥') then
begin
//Denne fortæller, at der ikke er noget svar endnu
lStr := ' ';
RetAutCode := PWideChar(lSTr);
Result := 0;
end
else
begin
//Svar ankommet. Laver den 2 lang med mellemrum imellem hver anden.
frmMain.mmoSvar.Lines.Add('1. '+lStr);
for i:=1 to 6 do
begin
l2 := l2 + lStr[i]+' ';
end;
frmMain.mmoSvar.Lines.Add('2. '+l2);
RetAutCode := PWideChar(l2);
frmMain.mmoSvar.Lines.Add('3. '+String(RetAutCode));
Result := 1;
if (not (frmMain.WriteKommPFil('9',1,KommPOfflineMark,KommPFyldTegn))) then;
end;
except
Result := 0;
end;
end;

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Ukendt (04-12-2007)
Kommentar
Fra : Ukendt


Dato : 04-12-07 09:36

"Michael Vilhelmsen"
<Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> skrev i
en meddelelse
news:mn.d29a7d7bbd3b3839.11460@Microcom.PLEASEREMOVE.Dk...
> Bedste resultat indtil nu er med:
>
> function OfflineAutoCode (var RetAutCode : PWideChar) : Integer;
> SafeCall;


Jeg vil sige:
- væk med VAR foran RetAutCode - det læser jeg ikke i
C-erklæringen - ingen grund til at overføre en pointer til en
pointer.
- Jeg plejer at bruge stdcall i stedet for safecall ved denne type
erklæringer, men jeg kan egentlig ikke sige at det er mere
korrekt.



Michael Vilhelmsen (04-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 04-12-07 09:56

Thomas Munk brought next idea :
> "Michael Vilhelmsen" <Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> skrev i en meddelelse news:mn.d29a7d7bbd3b3839.11460@Microcom.PLEASEREMOVE.Dk...
>> Bedste resultat indtil nu er med:
>>
>> function OfflineAutoCode (var RetAutCode : PWideChar) : Integer; SafeCall;
>
>
> Jeg vil sige:
> - væk med VAR foran RetAutCode - det læser jeg ikke i C-erklæringen - ingen grund til at overføre en pointer til en pointer.

Uden VAR virker det ikke.


> - Jeg plejer at bruge stdcall i stedet for safecall ved denne type erklæringer, men jeg kan egentlig ikke sige at det er mere korrekt.
StdCall giver et nedbrud.


Ellers Tak for info

Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Stig Johansen (07-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 07-12-07 05:52

Michael Vilhelmsen wrote:
> Thomas Munk brought next idea :
>> "Michael Vilhelmsen"
>> <Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> skrev i en
>> meddelelse news:mn.d29a7d7bbd3b3839.11460@Microcom.PLEASEREMOVE.Dk...
>>> Bedste resultat indtil nu er med:
>>>
>>> function OfflineAutoCode (var RetAutCode : PWideChar) : Integer;
>>> SafeCall;
>>
>>
>> Jeg vil sige:
>> - væk med VAR foran RetAutCode - det læser jeg ikke i C-erklæringen -
>> ingen grund til at overføre en pointer til en pointer.
>
> Uden VAR virker det ikke.

Hvis jeg var dig, ville jeg kigge efter en gang til.
Du blander pointere og dereferencing sammen - det er dømt til at fejle.

>> - Jeg plejer at bruge stdcall i stedet for safecall ved denne type
>> erklæringer, men jeg kan egentlig ikke sige at det er mere korrekt.
> StdCall giver et nedbrud.

Pga. memory overflow.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (07-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 07-12-07 11:39

Stig Johansen brought next idea :
> Michael Vilhelmsen wrote:
>> Thomas Munk brought next idea :
>>> "Michael Vilhelmsen"
>>> <Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> skrev i en
>>> meddelelse news:mn.d29a7d7bbd3b3839.11460@Microcom.PLEASEREMOVE.Dk...
>>>> Bedste resultat indtil nu er med:
>>>>
>>>> function OfflineAutoCode (var RetAutCode : PWideChar) : Integer;
>>>> SafeCall;
>>>
>>>
>>> Jeg vil sige:
>>> - væk med VAR foran RetAutCode - det læser jeg ikke i C-erklæringen -
>>> ingen grund til at overføre en pointer til en pointer.
>>
>> Uden VAR virker det ikke.
>
> Hvis jeg var dig, ville jeg kigge efter en gang til.
> Du blander pointere og dereferencing sammen - det er dømt til at fejle.

Jeg har prøvet adskillige forskellige kombinationer.
Den eneste jeg har fået til at virke og til at give mig præcis det ønskede resultat hver gang er den måde det er på nu.

Uden VAR får jeg en Access Violation.
Konsekvent.


>
>>> - Jeg plejer at bruge stdcall i stedet for safecall ved denne type
>>> erklæringer, men jeg kan egentlig ikke sige at det er mere korrekt.
>> StdCall giver et nedbrud.
>
> Pga. memory overflow.

Nej - Det giver en Access Violation.

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Stig Johansen (08-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 08-12-07 04:47

Michael Vilhelmsen wrote:

[snip]
> Uden VAR får jeg en Access Violation.
> Konsekvent.
[snip]
>> Pga. memory overflow.
> Nej - Det giver en Access Violation.

Ja - AV pga memory overflow.

Men hvis du er interesseret i at få det til at virke, så står løsningen i
bunden af denne her:
<http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_21255153.html>

Bemærk keywordet er cdecl og ikke stdcall/safecall.
--
Med venlig hilsen
Stig Johansen

Stig Johansen (08-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 08-12-07 05:21

Stig Johansen wrote:

> Men hvis du er interesseret i at få det til at virke, så står løsningen i
> bunden af denne her:
>
<http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_21255153.html>
>
> Bemærk keywordet er cdecl og ikke stdcall/safecall.

Og, det er nok også vigtigt at du finder ud af _hvem_ der håndterer memory
allocation af 'Code' i den her:
int pcbStopList (char *Code);

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (10-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 10-12-07 09:03

Stig Johansen was thinking very hard :
> Michael Vilhelmsen wrote:
>
> [snip]
>> Uden VAR får jeg en Access Violation.
>> Konsekvent.
> [snip]
>>> Pga. memory overflow.
>> Nej - Det giver en Access Violation.
>
> Ja - AV pga memory overflow.
>
> Men hvis du er interesseret i at få det til at virke, så står løsningen i
> bunden af denne her:
> <http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_21255153.html>
>
> Bemærk keywordet er cdecl og ikke stdcall/safecall.

Det er ganske fint alt det du skriver her - Det virker bare ikke.

Bruger cdecl og stdcall bryder programmet ned, når jeg forlader rutinen (med en AV).
Ud over denne ene rutine, er der i programmet mange andre callback rutiner.
De er også alle defineret som safecall.


Hvis der ikke er VAR på min parameter - Ja så virker programmet, men resultat kommer ikke frem

Denne definition:
function OfflineAutoCode (VAR RetAutCode : PWideChar) : Integer; SafeCall;


Den virker. Hver eneste gang. Uden AV eller noget.

Men kan nu egentlig godt følge dig i alt det du siger.
Jeg kan bare ikke få det til at virke på nogen af dine måder.
Dem som har sat DLLen tilrådighed - De er ikke overdrevent oplysende.
Så det er lidt svært at få informationer ad den vej.

Anyway - Programmet virker. Hver gang, som det er nu.
Alle andre kombinationer virker bare ikke. Eller giver en decideret AV.


Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Stig Johansen (11-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 11-12-07 04:29

Michael Vilhelmsen wrote:

> Det er ganske fint alt det du skriver her - Det virker bare ikke.

Ok, men så har vi forsøgt.

> Bruger cdecl og stdcall bryder programmet ned, når jeg forlader rutinen
> (med en AV). Ud over denne ene rutine, er der i programmet mange andre
> callback rutiner. De er også alle defineret som safecall.
>
>
> Hvis der ikke er VAR på min parameter - Ja så virker programmet, men
> resultat kommer ikke frem
>
> Denne definition:
> function OfflineAutoCode (VAR RetAutCode : PWideChar) : Integer; SafeCall;
>
>
> Den virker. Hver eneste gang. Uden AV eller noget.
>
> Men kan nu egentlig godt følge dig i alt det du siger.
> Jeg kan bare ikke få det til at virke på nogen af dine måder.
> Dem som har sat DLLen tilrådighed - De er ikke overdrevent oplysende.
> Så det er lidt svært at få informationer ad den vej.

Så er de squ tarvelige. Er der en .h med til DLL'en?
Hvis erklæringen er klippet over fra dokumentationen kan der være fejl i
den.

Som Thomas er inde på, er det en pointer, eller for den sags skyld en
adresse, der forventes jfr c-erklæringen.

Dvs. hvis vi eks. har (Hvis det er unicode).

Code : WideString ; (Den faktiske streng)
pCode : PWideString ; (32 bits adresse til den faktiske streng)

Så vil korrekte parametre være:
function OfflineAutoCode (VAR Code : WideString..
function OfflineAutoCode (pCode : PWideString..

Når du så bruger både VAR og pointer, er det en adresse til en adresse til
data. Det mener jeg ville hedde **Code i C.

Hvis du bruger Code skriver du eks:
Code := '123456' ;
Hvis du bruger pCode skriver du:
pCode^ := '123456' ;

Jeg har ikke selv brugt WideStrings (endnu) men strings er normal 0
termineret i Delphi.

Med det in mente, så:
*   FillChar(RetAutCode,SizeOf(RetAutCode),#0);
Her sætter du _adressen_ til NIL

*   lStr       := lStr + lStr;
Jeg er ikke med på om det er unicode eller ej. Det her bliver til 12
almindelige tegn, og ikke unicode.

*   RetAutCode := PWideChar(lSTr);
Her sætter du _adressen_ til det samme som iStr. Men _indholdet_ er stadig
12 almindelige tegn, og ikke unicode.

Jeg ville prøve denne her:
function OfflineAutoCode (var RetAutCode : WideString) : Integer; cdecl;
begin  //OfflineAutoCode
    RetAutCode := '123456';
    frmMain.lblInfo.Caption := RetAutCode;
    if (RetAutCode='¥¥¥¥¥¥') then
      Result     := 0
    else
      Result     := 1;
end;

Den burde virke jfr. c erklæringen. Hvis det ikke er unicode alligevel
bruger du bare en string i stedet.

> Anyway - Programmet virker. Hver gang, som det er nu.
> Alle andre kombinationer virker bare ikke. Eller giver en decideret AV.

Heller ikke den du lige har fået?

--
Med venlig hilsen
Stig Johansen

Stig Johansen (11-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 11-12-07 07:45

Stig Johansen wrote:

[Snip en masse]
Hov, det er *ekstremt* vigtigt at vide hvor hukommelsen til 'Code' bliver
allokeret.
Er det en *du* allokerer i forbindelse med noget 'init', eller er det en
reference til noget allokering i DLL filen?
Hvis det er en reference til en intern struktur i C-DLL'en kan du *ikke*
bruge varianter af string's i dit program.
Men som sagt hvis du har fået en .h fil samen med dll'en, så prøv lige at
smide (noget af) den her.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (11-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 11-12-07 09:26

Stig Johansen explained :
> Stig Johansen wrote:
>
> [Snip en masse]
> Hov, det er *ekstremt* vigtigt at vide hvor hukommelsen til 'Code' bliver
> allokeret.
> Er det en *du* allokerer i forbindelse med noget 'init', eller er det en
> reference til noget allokering i DLL filen?
> Hvis det er en reference til en intern struktur i C-DLL'en kan du *ikke*
> bruge varianter af string's i dit program.
> Men som sagt hvis du har fået en .h fil samen med dll'en, så prøv lige at
> smide (noget af) den her.

Ovenstående - Jeg har så aboslut ingen idé.

Dette er en procedure - en callback procedure.
Under opstarter kalder jeg en anden procedure fra DLLen for at fortælle hvilken function den kan kalde.
Det gør jeg sådan


flxInitCallback(FLX_CALLBACK_STOPLIST,@OfflineAutoCode);



Dette er definitionen af denne procedure.
procedure flxInitCallback(method_id:Integer; method_ptr:pointer); StdCall ; External 'flxdrv.dll';



Ved ikke om det oplyser noget som helst.

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Stig Johansen (12-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 12-12-07 04:43

Michael Vilhelmsen wrote:

> Stig Johansen explained :
>> Stig Johansen wrote:
>>
>> [Snip en masse]
>> Hov, det er *ekstremt* vigtigt at vide hvor hukommelsen til 'Code' bliver
>> allokeret.
>> Er det en *du* allokerer i forbindelse med noget 'init', eller er det en
>> reference til noget allokering i DLL filen?
>> Hvis det er en reference til en intern struktur i C-DLL'en kan du *ikke*
>> bruge varianter af string's i dit program.
>> Men som sagt hvis du har fået en .h fil samen med dll'en, så prøv lige at
>> smide (noget af) den her.
>
> Ovenstående - Jeg har så aboslut ingen idé.
>
> Dette er en procedure - en callback procedure.
> Under opstarter kalder jeg en anden procedure fra DLLen for at fortælle
> hvilken function den kan kalde. Det gør jeg sådan
>
> flxInitCallback(FLX_CALLBACK_STOPLIST,@OfflineAutoCode);
>
> Dette er definitionen af denne procedure.
> procedure flxInitCallback(method_id:Integer; method_ptr:pointer);
> StdCall ; External 'flxdrv.dll';
>
> Ved ikke om det oplyser noget som helst.

Ikke rigtig Michael.
Vi skal starte med at have fat i den der 'Code'.
Jeg har lige læst dit oprindelige klip igen. Hvis man (nær)læser det ordret,
så er der hverken tale om unicode eller 0-termineret streng.
Bemærk '..6 character...' og '...ECR may return 6 spaces (0x20)...'.
Hvis det er unicode må du have noget opdateret beskrivelse.

Ud fra beskrivelsen opfatter jeg den som array[1..6] of char, og ikke nogen
ekstra #0'er.
Har du mulighed for at undersøge hvad vi rent faktisk snakker om?

Det næste vi skal have fat i er _hvem_ der stiller memory til rådighed her.
Det normale er at 'hovedprogrammet' (dit) sørger for memory allokering. Hvis
det er tilfældet skal du have en _global_ variabel, du refererer til. I dit
eksempel med Istr, sætter du pointeren op til en lokal variabel(IStr), der
forsvinder fra stakken ved exit af funktionen. Hvis det virker beror det
alene på held, forstået på den måde, at stakken tilfældigvis er intakt
efter exit (=ikke overskrevet - *endnu*).

Hvis pointeren derimod referer til 6 bytes internt i DLL'en, må du under
ingen omstændigheder skriver hverken før eller efter - heller ikke trailing
#0 - , da du derved overskriver memory i DLL'en.

Kan du ikke prøve at sætte et breakpoint ved din funktion, og se hvad der
står i 'Code' ved entry. Altså er det en valid adresse, eller er det NIL,
og DLL'en forventer en adresse til din _globale_ variabel retur.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (12-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 12-12-07 09:10

>
> Ikke rigtig Michael.
> Vi skal starte med at have fat i den der 'Code'.
> Jeg har lige læst dit oprindelige klip igen. Hvis man (nær)læser det ordret,
> så er der hverken tale om unicode eller 0-termineret streng.
> Bemærk '..6 character...' og '...ECR may return 6 spaces (0x20)...'.
> Hvis det er unicode må du have noget opdateret beskrivelse.

Jeg har ikke mere beskrivelse end den, som er i første indlæg.
Og de gange jeg har henvendt mig for at få mere informationer, har ikke givet noget som helst jeg kan bruge.
Dem, som har udviklet denne DLL, er enten ekstremt uvillige til at give information fra sig (ikke utænkeligt som jeg kender dem) eller selv lige så uvidende om dette som jeg er



>
> Ud fra beskrivelsen opfatter jeg den som array[1..6] of char, og ikke nogen
> ekstra #0'er.
> Har du mulighed for at undersøge hvad vi rent faktisk snakker om?

Samme opfattelse her. Og som skrevet ovenfor - Ikke rigtig. Jeg får ingen respons tilbage, når jeg henvender mig.
Men jeg prøver lige igen ...


>
> Det næste vi skal have fat i er _hvem_ der stiller memory til rådighed her.
> Det normale er at 'hovedprogrammet' (dit) sørger for memory allokering. Hvis
> det er tilfældet skal du have en _global_ variabel, du refererer til. I dit
> eksempel med Istr, sætter du pointeren op til en lokal variabel(IStr), der
> forsvinder fra stakken ved exit af funktionen. Hvis det virker beror det
> alene på held, forstået på den måde, at stakken tilfældigvis er intakt
> efter exit (=ikke overskrevet - *endnu*).

Forstået - eller det tror jeg.
Fordi min parameter er af VAR typen vil den efter procedure kaldet pege på lStr, som efter proceduren exit'er ikke findes mere, men området tilfældigvis er intakt.




>
> Hvis pointeren derimod referer til 6 bytes internt i DLL'en, må du under
> ingen omstændigheder skriver hverken før eller efter - heller ikke trailing
> #0 - , da du derved overskriver memory i DLL'en.

Dette er faktisk hvad jeg tror der sker.
jeg tror, at pointeren henviser til 12 bytes (derfor widechar, som som jeg har forstået det fylder 2 bytes per tegn).
Derfor virker det, når jeg skriver korrekt til disse.

Men jeg har ikke andet end min intuition til at undertøtte dette.



>
> Kan du ikke prøve at sætte et breakpoint ved din funktion, og se hvad der
> står i 'Code' ved entry. Altså er det en valid adresse, eller er det NIL,
> og DLL'en forventer en adresse til din _globale_ variabel retur.


Code ved entry (Som jeg går ud fra du mener RetAutCode, som jeg kalder den) indeholder '' (Altså en tom streng).
Jeg har fjernet min FillChar (da jeg jo sagtens kan se, at den bare nulstiller min evt. pointer.

Så lige nu ser min funktion sådan ud:


function OfflineAutoCode (VAR RetAutCode : PWideChar) : Integer; SafeCall;
var
lStr : String;
i : Integer;
l2 : String;
begin //OfflineAutoCode
//Denne funktion skal bare informere et andet program om, at det skal til at reagere.
//Har ingen praktisk betydning
if (not (frmMain.WriteKommPFil(KommPAlBonYes,1,KommPOfflineMark,KommPFyldTegn))) then;

//Denne læser et svar fra et andet program
lStr := frmMain.LaesKommPFil(KommPOfflineAutCode,6);
try
//Hvis svaret er ¥¥¥¥¥¥ er der endnu intet svar
if (lStr='¥¥¥¥¥¥') then
begin
lStr := ' ';
//Jeg returnere 12 blanke.
RetAutCode := PWideChar(lSTr);
//Betyder, at der ikke må fortsættes i DLLen. Og det virker
Result := 0;
end
else
begin
//Her bygger jeg
for i:=1 to 6 do
begin
l2 := l2 + lStr[i]+' ';
end;
//Mit 12 cifrede svar returners til RetAutCode.
RetAutCode := PWideChar(l2);
//Jeg informere om, at svar er kommet, og der kan fortsættes.
Result := 1;
//Fortæller et andet program, at det er afleveret.
if (not (frmMain.WriteKommPFil('9',1,KommPOfflineMark,KommPFyldTegn))) then;
end;
except
Result := 0;
end;
end;

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Stig Johansen (13-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 13-12-07 06:48

Michael Vilhelmsen wrote:

>>
>> Ikke rigtig Michael.
>> Vi skal starte med at have fat i den der 'Code'.
>> Jeg har lige læst dit oprindelige klip igen. Hvis man (nær)læser det
>> ordret, så er der hverken tale om unicode eller 0-termineret streng.
>> Bemærk '..6 character...' og '...ECR may return 6 spaces (0x20)...'.
>> Hvis det er unicode må du have noget opdateret beskrivelse.
>
> Jeg har ikke mere beskrivelse end den, som er i første indlæg.
> Og de gange jeg har henvendt mig for at få mere informationer, har ikke
> givet noget som helst jeg kan bruge. Dem, som har udviklet denne DLL, er
> enten ekstremt uvillige til at give information fra sig (ikke utænkeligt
> som jeg kender dem) eller selv lige så uvidende om dette som jeg er

Jeg vil umiddelbart gætte på begge dele, professionelt er det i hvertfald
ikke.

>> Ud fra beskrivelsen opfatter jeg den som array[1..6] of char, og ikke
>> nogen ekstra #0'er.
>> Har du mulighed for at undersøge hvad vi rent faktisk snakker om?
>
> Samme opfattelse her. Og som skrevet ovenfor - Ikke rigtig. Jeg får ingen
> respons tilbage, når jeg henvender mig. Men jeg prøver lige igen ...

Jamen Michael - nogen må have skrevet eller sagt et eller andet som gør at
det skal opfattes som unicode. Der er også den mulighed, at dem der har
leveret DLL'en ikke selv har lavet/opdateret den, og dermed måske ikke ved
hvad de snakker om.

Du får lige en præcisering.
*Unicode* er en betegnelse for flere implementeringer. Principielt
foretrækker man UTF-8, men her er antallet af bytes/karakter variabelt.
Man kan derfor ikke referere til ting som Length(String), String[x] osv.
For at kunne håndtere den slags ting internt, bruger Windows UCS-2, og Linux
UCS-4.
Vi er altså ovre i UCS-2 - *hvis* det er 'unicode', som er hhv WideChar og
WideString i Delphi.
De fylder ganske rigtig 2 bytes pr. karakter, men det skal opfattes som et
16bits tal, og ikke blank+karakter.

Jeg har fundet en side, jeg synes der beskriver tingene ganske godt:
<http://gedcom-parse.sourceforge.net/doc/encoding.html>
I forhold til det jeg skriver nu, skal du lige læse det afsnit, der hedder
"Unicode encodings, UTF-8", og især tabellen med byte values UCS-2.

Prøv så at høre her - og det er ikke nedladende.
Hvis du returnerer 12 'blanke' tegn er det *ikke* 6 UCS-2 blanke, men en
eller anden for for mystisk karakter - hov kommer lige i tanke om, at jeg
har et program på denne her Linux spand .....
Jo den er god nok, x20AC *er* euro tegn, prøver lige at finde x2020 ...
... du tror det er løwn .. det er et kors som dem der står i kirken. Er det
nu vi skal gøre 'korsets tegn' for at få det til at virke?

For at rekapitulere:
12 Blanke er x20,x20,x20 som er lig 6 x2020,x2020... Altså burde du se 6
'kors' som returværdi.

>> Det næste vi skal have fat i er _hvem_ der stiller memory til rådighed
>> her. Det normale er at 'hovedprogrammet' (dit) sørger for memory
>> allokering. Hvis det er tilfældet skal du have en _global_ variabel, du
>> refererer til. I dit eksempel med Istr, sætter du pointeren op til en
>> lokal variabel(IStr), der forsvinder fra stakken ved exit af funktionen.
>> Hvis det virker beror det alene på held, forstået på den måde, at stakken
>> tilfældigvis er intakt efter exit (=ikke overskrevet - *endnu*).
>
> Forstået - eller det tror jeg.
> Fordi min parameter er af VAR typen vil den efter procedure kaldet pege på
> lStr, som efter proceduren exit'er ikke findes mere, men området
> tilfældigvis er intakt.

Ikke helt, det var lokale ctr. globale variable.
*** globale:
var
i : integer ;
function x(p:pointer):integer;
begin
p := @i ;
result := 1;
end;
her bliver p sat til adressen på i, og da i stadig eksistere på samme
adresse efter funktionens afslutning, er den valid.

*** lokale:
function x(p:pointer):integer;
var
i : integer ;
begin
p := @i ;
result := 1;
end;
her bliver p også sat til adressen på i, men i eksisterer kun 'inde' i
funktionen. Når funktionen afsluttes peger p på den fysiske adresse som i
havde dengang funktionen var aktiv, men adressen er nu 'til genbrug'. I det
omfang hukommelsen ikke er 'genbrugt' vil den 'tilfældigvis' indeholde de
samme data.

>> Hvis pointeren derimod referer til 6 bytes internt i DLL'en, må du under
>> ingen omstændigheder skriver hverken før eller efter - heller ikke
>> trailing
>> #0 - , da du derved overskriver memory i DLL'en.
>
> Dette er faktisk hvad jeg tror der sker.
> jeg tror, at pointeren henviser til 12 bytes (derfor widechar, som som jeg
> har forstået det fylder 2 bytes per tegn). Derfor virker det, når jeg
> skriver korrekt til disse.

Nu må du ikke blive sur, men du skriver ikke *korrekt* UCS-2 til disse, og
det burde under *ingen* omstøndigheder virke.

Ok, kommer lige i tanke om.....
Det *kan* tænkes, at de har forholdt sig til kompatibiliteten til ISO8859-1
og har lavet en høkerløsning med kun at læse hvert andet tegn. Men så er
det *ikke* unicode, men '2 bytes' ISO8859-1.

> Men jeg har ikke andet end min intuition til at undertøtte dette.

Næ, det er lidt noget fis når 'leverandøren' ikke er i stand til at give de
fornødne oplysninger.
Nu håber jeg ikke jeg har været for grov, men du kan godt se, at der ikke er
sammenhæng mellem det de _skriver_, det de _gør_ i DLL'en og _unicode_.

Så oppe i mit hovede er konklusionen ganske klar: Din 'leverandør' af DLL'en
aner ikke en hujende fis om hvad de laver.

Men det kan vi ikke bruge til noget, det gør bare at 'vi' selv må finde ud
af tingene.

>> Kan du ikke prøve at sætte et breakpoint ved din funktion, og se hvad der
>> står i 'Code' ved entry. Altså er det en valid adresse, eller er det NIL,
>> og DLL'en forventer en adresse til din _globale_ variabel retur.
>
>
> Code ved entry (Som jeg går ud fra du mener RetAutCode, som jeg kalder
> den) indeholder '' (Altså en tom streng). Jeg har fjernet min FillChar (da
> jeg jo sagtens kan se, at den bare nulstiller min evt. pointer.

Jo, det er den. Jeg sad bare og kiggede på 'c' beskrivelsen.

> Så lige nu ser min funktion sådan ud:
> function OfflineAutoCode (VAR RetAutCode : PWideChar) : Integer; SafeCall;

Hvis du gerne vil til bunds i det her, forstået på den måde, at 'vi' bliver
nødt til at 'prøve os frem' fordi du ikke kan få de korrekte oplysninger,
så vil jeg foreslå følgende fremgangsmåde.

Vi har principielt en ligning med to variable, det plejer at være noget hø
inden for matematikken, men here it goes:

1. Variabel i vores ligning: Calling convention. Calling convention er i
princippet en slags 'kontrakt' mellem 2 funktioner. 'Kontrakten' indeholder
oplysninger om hvilken rækkefølge parametre optræder i, samt hvem der
rydder op ved exit.
I Delphi har vi følgende:
* Ingenting - Pascal til pascal.
* Stdcall - Typisk Pascal <> C
* Safecall - En afart af Pascal <> C
* Cdecl - Endnu en afart af Pascal <> C

Det er den første udfordring, som 'vi' ikke kan få oplyst: 'Hvilken calling
convention bruger DLL'en?". Det er det kaldende program, der bestemmer. Det
er muligt at der er flere, der virker, men det er vigtig at huske på, at
der i denne funktion kun er 1 parameter, så *her' er det ligegyldigt om
rækkefølgen er forfra eller bagfra.

2. Variabel i vores ligning: "char *Code". Her skal vi huske, at C er mere
eller mindre typeløst. En 'char' kan ligesågodt være det vi i Delphi kalder
Byte, Pointer til en funktion, array osv. Det er først i (C) koden man
tager stilling hvad det egentlig er for noget.
Det er derfor C er sproget hvor man har mulighed for at skyde alle fødderne
af sig selv uden at ane hvem eller hvilken hånd der skød.
Godt så, "char *Code" siger intet i sig selv, andet end det er en eller
anden form for pointer til et eller andet.

Det var lidt snak om selve funktionserklæringen.

> var
> lStr : String;
> i : Integer;
> l2 : String;

Lidt afhængig af udfaldet, skal noget af det flyttes op i den globale
afdeling.

> begin //OfflineAutoCode
> //Denne funktion skal bare informere et andet program om, at det skal
> til at reagere. //Har ingen praktisk betydning
> if (not
> (frmMain.WriteKommPFil(KommPAlBonYes,1,KommPOfflineMark,KommPFyldTegn)))
> then;
>
> //Denne læser et svar fra et andet program
> lStr := frmMain.LaesKommPFil(KommPOfflineAutCode,6);
> try
> //Hvis svaret er ¥¥¥¥¥¥ er der endnu intet svar
> if (lStr='¥¥¥¥¥¥') then
> begin
> lStr := ' ';
> //Jeg returnere 12 blanke.
> RetAutCode := PWideChar(lSTr);

Nej, du returnerer en *pointer* til 12 blanke (+ '#0'), det er ligegyldigt
om du skriver Pchar(),PWideChar,@lStr[1] osv..

> //Betyder, at der ikke må fortsættes i DLLen. Og det virker
> Result := 0;
> end
> else
> begin
> //Her bygger jeg
> for i:=1 to 6 do
> begin
> l2 := l2 + lStr[i]+' ';
> end;
> //Mit 12 cifrede svar returners til RetAutCode.
> RetAutCode := PWideChar(l2);

Nej igen, du returnerer en *pointer*, nu til l2.

> //Jeg informere om, at svar er kommet, og der kan fortsættes.
> Result := 1;
> //Fortæller et andet program, at det er afleveret.
> if (not
> (frmMain.WriteKommPFil('9',1,KommPOfflineMark,KommPFyldTegn))) then;
> end;
> except
> Result := 0;
> end;
> end;
Her afslutter du funktionen, både l2 og lStr går ud af scope, og er til
'fri' afbenyttelse. Den *pointer* du har givet til DLL'en peger nu på data
'du ikke kan stole på'. Hvis du skal 'sikre' dig, skal du flytte lStr + l2
op i din globale var sektion.

Hvad kan 'vi' så gøre nu?
Som nævnt betyder *Code blot en pointer i C. Det kan sagtens tænkes, at man
i DLL'en bruger den som pointer, og dermed bliver det en pointer til en
pointer osv. Her skal man huske, at der er ikke noget der hedder 'VAR' i C,
samt at VAR i Pascal blot er en anden måde at beskrive en pointer som
parameter.

Disse 2 erklæringer er identiske set fra en 'ekstern' funktion:
Function A (var p1 : Char) : Integer ;
Function B (p1 : pChar ) : Integer ;
i begge tilfælde overføres p1 som en pointer til Char.

Bruger man derimod
Function C (var p1 : pChar ) : Integer ;
i bliver overføres p1 som en pointer til en pointer til en Char.

Det er C varianten du bruger nu. Det betyder ikke, at det ikke er rigtigt,
det betyder bare at din dokumentation er *forkert* - men det har vi
allerede fundet ud af.

Jeg ved egentlig ikke rigtig hvor meget vi skal gøre ud af det her - du
skriver det virker, så det er måske 'godt nok'. Jeg ville måske føle mig
utryg ved ikke at vide *hvorfor* det virker. Men igen det er de sataner,
der har leveret DLL'en, der sidder på oplysningerne, vi andre kan kun
'prøve os frem'.

Under alle omstændigheder synes jeg du skal flytte de 2 'strenge' op i den
globale sektion (Og måske lige give dem nogle sigende navne). Så er du i
det mindste sikker på ikke at få ubehagelige overraskelser på den konto.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (13-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 13-12-07 09:10

Wauw - Det var lidt af en smøre

Men lad mig starte med det første først.
Jeg tager ikke skade af lidt kritik - Faktisk er det jo den eneste måde man lære på



>
>>> Ud fra beskrivelsen opfatter jeg den som array[1..6] of char, og ikke
>>> nogen ekstra #0'er.
>>> Har du mulighed for at undersøge hvad vi rent faktisk snakker om?
>>
>> Samme opfattelse her. Og som skrevet ovenfor - Ikke rigtig. Jeg får ingen
>> respons tilbage, når jeg henvender mig. Men jeg prøver lige igen ...
>
> Jamen Michael - nogen må have skrevet eller sagt et eller andet som gør at
> det skal opfattes som unicode. Der er også den mulighed, at dem der har
> leveret DLL'en ikke selv har lavet/opdateret den, og dermed måske ikke ved
> hvad de snakker om.
>
> Du får lige en præcisering.
> *Unicode* er en betegnelse for flere implementeringer. Principielt
> foretrækker man UTF-8, men her er antallet af bytes/karakter variabelt.
> Man kan derfor ikke referere til ting som Length(String), String[x] osv.
> For at kunne håndtere den slags ting internt, bruger Windows UCS-2, og Linux
> UCS-4.
> Vi er altså ovre i UCS-2 - *hvis* det er 'unicode', som er hhv WideChar og
> WideString i Delphi.
> De fylder ganske rigtig 2 bytes pr. karakter, men det skal opfattes som et
> 16bits tal, og ikke blank+karakter.
>
> Jeg har fundet en side, jeg synes der beskriver tingene ganske godt:
> <http://gedcom-parse.sourceforge.net/doc/encoding.html>
> I forhold til det jeg skriver nu, skal du lige læse det afsnit, der hedder
> "Unicode encodings, UTF-8", og især tabellen med byte values UCS-2.
>
> Prøv så at høre her - og det er ikke nedladende.
> Hvis du returnerer 12 'blanke' tegn er det *ikke* 6 UCS-2 blanke, men en
> eller anden for for mystisk karakter - hov kommer lige i tanke om, at jeg
> har et program på denne her Linux spand .....
> Jo den er god nok, x20AC *er* euro tegn, prøver lige at finde x2020 ...
> .. du tror det er løwn .. det er et kors som dem der står i kirken. Er det
> nu vi skal gøre 'korsets tegn' for at få det til at virke?
>
> For at rekapitulere:
> 12 Blanke er x20,x20,x20 som er lig 6 x2020,x2020... Altså burde du se 6
> 'kors' som returværdi.

De der kors - Dem så jeg faktisk kort på et eller andet tidspunkt, hvor jeg skrev noget information til mig selv på skærmen
Så helt ved siden af, er vi ikke (eller er du ikke ).


>
>>> Det næste vi skal have fat i er _hvem_ der stiller memory til rådighed
>>> her. Det normale er at 'hovedprogrammet' (dit) sørger for memory
>>> allokering. Hvis det er tilfældet skal du have en _global_ variabel, du
>>> refererer til. I dit eksempel med Istr, sætter du pointeren op til en
>>> lokal variabel(IStr), der forsvinder fra stakken ved exit af funktionen.
>>> Hvis det virker beror det alene på held, forstået på den måde, at stakken
>>> tilfældigvis er intakt efter exit (=ikke overskrevet - *endnu*).
>>
>> Forstået - eller det tror jeg.
>> Fordi min parameter er af VAR typen vil den efter procedure kaldet pege på
>> lStr, som efter proceduren exit'er ikke findes mere, men området
>> tilfældigvis er intakt.
>
> Ikke helt, det var lokale ctr. globale variable.
> *** globale:
> var
> i : integer ;
> function x(p:pointer):integer;
> begin
> p := @i ;
> result := 1;
> end;
> her bliver p sat til adressen på i, og da i stadig eksistere på samme
> adresse efter funktionens afslutning, er den valid.
>
> *** lokale:
> function x(p:pointer):integer;
> var
> i : integer ;
> begin
> p := @i ;
> result := 1;
> end;
> her bliver p også sat til adressen på i, men i eksisterer kun 'inde' i
> funktionen. Når funktionen afsluttes peger p på den fysiske adresse som i
> havde dengang funktionen var aktiv, men adressen er nu 'til genbrug'. I det
> omfang hukommelsen ikke er 'genbrugt' vil den 'tilfældigvis' indeholde de
> samme data.

Forstået.



>
>>> Hvis pointeren derimod referer til 6 bytes internt i DLL'en, må du under
>>> ingen omstændigheder skriver hverken før eller efter - heller ikke
>>> trailing
>>> #0 - , da du derved overskriver memory i DLL'en.
>>
>> Dette er faktisk hvad jeg tror der sker.
>> jeg tror, at pointeren henviser til 12 bytes (derfor widechar, som som jeg
>> har forstået det fylder 2 bytes per tegn). Derfor virker det, når jeg
>> skriver korrekt til disse.
>
> Nu må du ikke blive sur, men du skriver ikke *korrekt* UCS-2 til disse, og
> det burde under *ingen* omstøndigheder virke.
>
> Ok, kommer lige i tanke om.....
> Det *kan* tænkes, at de har forholdt sig til kompatibiliteten til ISO8859-1
> og har lavet en høkerløsning med kun at læse hvert andet tegn. Men så er
> det *ikke* unicode, men '2 bytes' ISO8859-1.

>
>> Men jeg har ikke andet end min intuition til at undertøtte dette.
>
> Næ, det er lidt noget fis når 'leverandøren' ikke er i stand til at give de
> fornødne oplysninger.
> Nu håber jeg ikke jeg har været for grov, men du kan godt se, at der ikke er
> sammenhæng mellem det de _skriver_, det de _gør_ i DLL'en og _unicode_.


Overhovedet ikke...

Jeg har lært noget af dette.
Der er lidt af dette her, som ikke står helt klart for mig. Endnu ...
Det begynder så småt at dæmre for mig - Og så går vi jo den rigtige vej ...


>
> Så oppe i mit hovede er konklusionen ganske klar: Din 'leverandør' af DLL'en
> aner ikke en hujende fis om hvad de laver.

På dette punkt er vi fuldstændig engie !!!
Og det gælder nu også deres service - Men det er en helt anden ting.


>
> Men det kan vi ikke bruge til noget, det gør bare at 'vi' selv må finde ud
> af tingene.
>
>>> Kan du ikke prøve at sætte et breakpoint ved din funktion, og se hvad der
>>> står i 'Code' ved entry. Altså er det en valid adresse, eller er det NIL,
>>> og DLL'en forventer en adresse til din _globale_ variabel retur.
>>
>>
>> Code ved entry (Som jeg går ud fra du mener RetAutCode, som jeg kalder
>> den) indeholder '' (Altså en tom streng). Jeg har fjernet min FillChar (da
>> jeg jo sagtens kan se, at den bare nulstiller min evt. pointer.
>
> Jo, det er den. Jeg sad bare og kiggede på 'c' beskrivelsen.
>
>> Så lige nu ser min funktion sådan ud:
>> function OfflineAutoCode (VAR RetAutCode : PWideChar) : Integer; SafeCall;
>
> Hvis du gerne vil til bunds i det her, forstået på den måde, at 'vi' bliver
> nødt til at 'prøve os frem' fordi du ikke kan få de korrekte oplysninger,
> så vil jeg foreslå følgende fremgangsmåde.
>
> Vi har principielt en ligning med to variable, det plejer at være noget hø
> inden for matematikken, men here it goes:
>
> 1. Variabel i vores ligning: Calling convention. Calling convention er i
> princippet en slags 'kontrakt' mellem 2 funktioner. 'Kontrakten' indeholder
> oplysninger om hvilken rækkefølge parametre optræder i, samt hvem der
> rydder op ved exit.
> I Delphi har vi følgende:
> * Ingenting - Pascal til pascal.
> * Stdcall - Typisk Pascal <> C
> * Safecall - En afart af Pascal <> C
> * Cdecl - Endnu en afart af Pascal <> C
>
> Det er den første udfordring, som 'vi' ikke kan få oplyst: 'Hvilken calling
> convention bruger DLL'en?". Det er det kaldende program, der bestemmer. Det
> er muligt at der er flere, der virker, men det er vigtig at huske på, at
> der i denne funktion kun er 1 parameter, så *her' er det ligegyldigt om
> rækkefølgen er forfra eller bagfra.
>
> 2. Variabel i vores ligning: "char *Code". Her skal vi huske, at C er mere
> eller mindre typeløst. En 'char' kan ligesågodt være det vi i Delphi kalder
> Byte, Pointer til en funktion, array osv. Det er først i (C) koden man
> tager stilling hvad det egentlig er for noget.
> Det er derfor C er sproget hvor man har mulighed for at skyde alle fødderne
> af sig selv uden at ane hvem eller hvilken hånd der skød.
> Godt så, "char *Code" siger intet i sig selv, andet end det er en eller
> anden form for pointer til et eller andet.



Hm - C lyder ikke som et sprog jeg vil befinde mig godt i.
Men det er forstået, det som du skriver.





>
> Det var lidt snak om selve funktionserklæringen.
>
>> var
>> lStr : String;
>> i : Integer;
>> l2 : String;
>
> Lidt afhængig af udfaldet, skal noget af det flyttes op i den globale
> afdeling.
>
>> begin //OfflineAutoCode
>> //Denne funktion skal bare informere et andet program om, at det skal
>> til at reagere. //Har ingen praktisk betydning
>> if (not
>> (frmMain.WriteKommPFil(KommPAlBonYes,1,KommPOfflineMark,KommPFyldTegn)))
>> then;
>>
>> //Denne læser et svar fra et andet program
>> lStr := frmMain.LaesKommPFil(KommPOfflineAutCode,6);
>> try
>> //Hvis svaret er ¥¥¥¥¥¥ er der endnu intet svar
>> if (lStr='¥¥¥¥¥¥') then
>> begin
>> lStr := ' ';
>> //Jeg returnere 12 blanke.
>> RetAutCode := PWideChar(lSTr);
>
> Nej, du returnerer en *pointer* til 12 blanke (+ '#0'), det er ligegyldigt
> om du skriver Pchar(),PWideChar,@lStr[1] osv..
>


Forstået.



>> //Betyder, at der ikke må fortsættes i DLLen. Og det virker
>> Result := 0;
>> end
>> else
>> begin
>> //Her bygger jeg
>> for i:=1 to 6 do
>> begin
>> l2 := l2 + lStr[i]+' ';
>> end;
>> //Mit 12 cifrede svar returners til RetAutCode.
>> RetAutCode := PWideChar(l2);
>
> Nej igen, du returnerer en *pointer*, nu til l2.

Forstået.



>
>> //Jeg informere om, at svar er kommet, og der kan fortsættes.
>> Result := 1;
>> //Fortæller et andet program, at det er afleveret.
>> if (not
>> (frmMain.WriteKommPFil('9',1,KommPOfflineMark,KommPFyldTegn))) then;
>> end;
>> except
>> Result := 0;
>> end;
>> end;
> Her afslutter du funktionen, både l2 og lStr går ud af scope, og er til
> 'fri' afbenyttelse. Den *pointer* du har givet til DLL'en peger nu på data
> 'du ikke kan stole på'. Hvis du skal 'sikre' dig, skal du flytte lStr + l2
> op i din globale var sektion.

Jeg flytter dem for god ordens skyld op i den globale sektion.
Så er vi sikre på, at de er der hele tiden.
Point taken ...



>
> Hvad kan 'vi' så gøre nu?
> Som nævnt betyder *Code blot en pointer i C. Det kan sagtens tænkes, at man
> i DLL'en bruger den som pointer, og dermed bliver det en pointer til en
> pointer osv. Her skal man huske, at der er ikke noget der hedder 'VAR' i C,
> samt at VAR i Pascal blot er en anden måde at beskrive en pointer som
> parameter.
>
> Disse 2 erklæringer er identiske set fra en 'ekstern' funktion:
> Function A (var p1 : Char) : Integer ;
> Function B (p1 : pChar ) : Integer ;
> i begge tilfælde overføres p1 som en pointer til Char.
>
> Bruger man derimod
> Function C (var p1 : pChar ) : Integer ;
> i bliver overføres p1 som en pointer til en pointer til en Char.
>
> Det er C varianten du bruger nu. Det betyder ikke, at det ikke er rigtigt,
> det betyder bare at din dokumentation er *forkert* - men det har vi
> allerede fundet ud af.





>
> Jeg ved egentlig ikke rigtig hvor meget vi skal gøre ud af det her - du
> skriver det virker, så det er måske 'godt nok'. Jeg ville måske føle mig
> utryg ved ikke at vide *hvorfor* det virker. Men igen det er de sataner,
> der har leveret DLL'en, der sidder på oplysningerne, vi andre kan kun
> 'prøve os frem'.
>
> Under alle omstændigheder synes jeg du skal flytte de 2 'strenge' op i den
> globale sektion (Og måske lige give dem nogle sigende navne). Så er du i
> det mindste sikker på ikke at få ubehagelige overraskelser på den konto.



Det er i hvert fald det mindste jeg gør.
Hver morgen når jeg møder, og tiden tillader det, afprøver jeg det, som du har skrevet.

Som du selv skriver, så er der ikke noget værere end at have et program, som ser ud til at virke, men man ved ikke hvorfor ..


Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Michael Vilhelmsen (13-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 13-12-07 09:53

NÃ¥ - SÃ¥ fik jeg et svar.
Det er kort, men i det mindste er der et svar.



FRA MAIL START*****

Hej,

Code er en '\0' termineret ascii (8-bit) streng med længden 6+1 bytes, som applikationen 'ejer'.

Her er et kode eksempel i c som lader sig kalde 5 gange før den returnerer 1.


int checkStopList(char *code)
{
static int cnt=0;

strcpy(code,"PointX");
printf("checkStopList [%s]\n",code);
if (++cnt==5) return 1;
return 0;
}

******** SLUT


Se - det er den mængde information man kan forvente.
Sammen med den tidligere korte beskrivelse (1. indlæg) er det,hvad jeg har.


Jeg ved ikke rigtig hvad jeg skal sige til dette.
Men det betyder, at jeg skal returnere 6 chars + #0.
Det er en Char og ikke widechar.
Den kombination kan jeg bare ikke få til at virke.





For at give et andet eksempel, har jeg en anden callback procedure.
Den er som sådan (aner ikke om det hjælper noget, men here goes...).


5.4.4 The printStatus call-back routine

Synopsis
void printStatus( const char cStat[21], unsigned int line );

Description
printStatus is used to show the terminals statuses on the ECR Display. The Flex-driver automatically calls printStatus when the status changes.
cStat is coded as ISO 8859-15 and is 0 terminated with a maximum length of 21 incl. '\0'.
The ‘line’ parameter is the terminal suggestion to which status line the text should be placed. Four lines are supported in the terminal. Values are 0x01 for line1, 0x02 for line2 etc. This function
is mandatory to implement.

Return value None


Det, som denne rutine skal gøre, er at give mig en tekstlinie (med op til 21 tegn), samt et linienummer den kan stå i (pt 1-5).
Min implementering af denne er:


Const
DispLaengde = 21;

Type
TPCharDisp = array [0..DispLaengde] of WideChar;


procedure Display_Status (var Cstat1: TPCharDisp; line : Integer); SafeCall;
var
Lst : String;
ii : Integer;
Begin //Display_Status
try
Lst := '';
ii := 0;
While (ii<=DispLaengde) and (Ord(cStat1[ii])<>0) do
begin
if (Ord(cStat1[ii])>20) and (Ord(cStat1[ii])<SkilleTegn) then
begin
LSt := LSt + cStat1[ii];
end
else if (ord(cStat1[ii])=0) then
begin
end
else if (ord(cStat1[ii])=10) then
begin
LST := Lst + #13#10;
end;
INC(ii);
end;

Case line of
1:
begin
frmMain.lblDisp1.Caption := Lst;
frmMain.lblDisp1.Update;
end;
2:
begin
frmMain.lblDisp2.Caption := Lst;
frmMain.lblDisp2.Update;
end;
3:
begin
frmMain.lblDisp3.Caption := Lst;
frmMain.lblDisp3.Update;
end;
4:
begin
frmMain.lblDisp4.Caption := Lst;
frmMain.lblDisp4.Update;
end;
else
begin
frmMain.lblDisp5.Caption := Lst;
frmMain.lblDisp5.Update;
end;
end;
except
end;
end;



Denne rutine virker.
Det jeg forsøger at lave er kommunikation med en kreditkorts terminal.
I forbindelse med en ekspedition, vil terminal f.eks. skrive INDLÆS KORT.
Denne tekst skal således afspejles på min PC. Og det bliver den med ovenstående callback funktion.





For at initiere disse callback funktioner jeg skal skrive, gør jeg sådan under opstart af programmet:


flxInitCallback(FLX_CALLBACK_STOPLIST,@OfflineAutoCode);
flxInitCallback(FLX_CALLBACK_DISPLAY_STATUS,@Display_Status);


Hvor følgende er defineret:

CONST
FLX_CALLBACK_DISPLAY_STATUS = 102;
FLX_CALLBACK_STOPLIST = 122;


procedure flxInitCallback(method_id:Integer; method_ptr:pointer); StdCall ; External 'flxdrv.dll';



Dvs. - Jeg fortæller flxdrv, at den kan kalde forskellige rutiner i mit program, og at de ligger på adresse xxxx, korrekt ?




men som du ser, benytter jeg i denne rutine også widechars. Widechar fylder 16 bits.
Men en ISO 8859-15 fylder kun 8 - Så efter min mening må der gå et eller andet galt hos dem, undervejs eller hos mig.

Jeg kan huske, da jeg lavede det oprindeligt kæmpede jeg også med ovenstående procedure, hvor jeg bruge alm. chars.
Det virkede bare ikke, før jeg brugte widechars - Og det passer ikke med den definition som jeg har.




Jeg vil lige vente med at prøve mere lige nu - I hvert fald lige indtil du har kommenteret denne besked.

Og igen - Tusind tak for hjælpen.
Skulle du endag komme forbi Odense - SÃ¥ sig til.
Jeg giver gerne en kop kaffe og et stykke brød

Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Michael Vilhelmsen (13-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 13-12-07 10:14

Stig Johansen formulated the question :
> Prøv så at høre her - og det er ikke nedladende.
> Hvis du returnerer 12 'blanke' tegn er det *ikke* 6 UCS-2 blanke, men en
> eller anden for for mystisk karakter - hov kommer lige i tanke om, at jeg
> har et program på denne her Linux spand .....
> Jo den er god nok, x20AC *er* euro tegn, prøver lige at finde x2020 ...
> .. du tror det er løwn .. det er et kors som dem der står i kirken. Er det
> nu vi skal gøre 'korsets tegn' for at få det til at virke?
>
> For at rekapitulere:
> 12 Blanke er x20,x20,x20 som er lig 6 x2020,x2020... Altså burde du se 6
> 'kors' som returværdi.


I det tilfælde hvor jeg returnere de 12 blanke benyttes de ikke af "kalder" da jeg returnere 0.
Så jeg kan returnere lige hvad jeg vil

Når jeg først returnere 1 - Så skal der returneres noget som kan læses af "kalder".
Jeg har lavet mine variable globale nu.
Så er jeg da sikker på den del.

Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Michael Vilhelmsen (13-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 13-12-07 10:20

After serious thinking Stig Johansen wrote :
> Jeg ved egentlig ikke rigtig hvor meget vi skal gøre ud af det her - du
> skriver det virker, så det er måske 'godt nok'. Jeg ville måske føle mig
> utryg ved ikke at vide *hvorfor* det virker. Men igen det er de sataner,
> der har leveret DLL'en, der sidder på oplysningerne, vi andre kan kun
> 'prøve os frem'.

Det samme her.

Det virker.
Det er det primære.
Så kan det komme i produktion.

Det irritere mig bare helt vildt, at:

- Oplysningen siger 8 bits char 0 termineret
- Jeg kan kun få det til at virke med 16 bits char.
- At informationen fra vores leverandør er SÅÅ informativ.
- At det virker uden jeg helt ved hvorfor.



>
> Under alle omstændigheder synes jeg du skal flytte de 2 'strenge' op i den
> globale sektion (Og måske lige give dem nogle sigende navne). Så er du i
> det mindste sikker på ikke at få ubehagelige overraskelser på den konto.


Dette er gjort.


Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Stig Johansen (14-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 14-12-07 07:30

Michael Vilhelmsen wrote:

> After serious thinking Stig Johansen wrote :
>> Jeg ved egentlig ikke rigtig hvor meget vi skal gøre ud af det her - du
>> skriver det virker, så det er måske 'godt nok'. Jeg ville måske føle mig
>> utryg ved ikke at vide *hvorfor* det virker. Men igen det er de sataner,
>> der har leveret DLL'en, der sidder på oplysningerne, vi andre kan kun
>> 'prøve os frem'.
>
> Det samme her.
>
> Det virker.
> Det er det primære.
> Så kan det komme i produktion.
>
> Det irritere mig bare helt vildt, at:
>
> - Oplysningen siger 8 bits char 0 termineret
> - Jeg kan kun få det til at virke med 16 bits char.
> - At informationen fra vores leverandør er SÅÅ informativ.
> - At det virker uden jeg helt ved hvorfor.

Jeg prøver lige at kommentere lidt fra de forskellige svar i denne her, der
er ingen garanti for struktur.

> Det jeg forsøger at lave er kommunikation med en kreditkorts terminal.

He he, den havde jeg kuret fra starten. Når 'the old man', der bla har lavet
banksystemer i 10 år ser ord som 'PBS','Dankort' osv. Netop derfor er det
vigtig (synes jeg) at det er 'korrekt'.

Du skal lige abstrahere fra det der 'unicode', jeg vil kommentere ud fra
'normale' tegn. Så kan jeg bedre selv forstå hvad jeg skriver. Så til ta'r
vi 'unicode' delen.

Ovre fra 'mail' en:
> Code er en '\0' termineret ascii (8-bit) streng med længden 6+1 bytes, som
> applikationen 'ejer'.

Mailen er kort, men her ligger rent faktisk svaret på et af de spørgsmål jeg
har stillet.
(Hov, det er ekstremt vigtigt at vide hvor hukommelsen til 'Code' bliver
allokeret.)
Det er forskellige ordvalg, men applikationen 'ejer' betyder, at det er
*dit* program, der er ansvarlig for hukommelsen. Det er også det normale
ved brug af dll'er.
Skal vi fortolke denne her ordret er ækvivalenten array[0..6] of char.

Lad mig lige hoppe over til din 'print'..
> void printStatus( const char cStat[21], unsigned int line );
og
> with a maximum length of 21 incl. '\0'.
Denne her er array[0..20] of char og ikke [0..21].
Læg mærke til *incl* '\0', det giver 20 tegn på display'et.

Når jeg ser denne her:
> if (Ord(cStat1[ii])>20) and (Ord(cStat1[ii])<SkilleTegn) then
Før jeg indtrykket af, at du har haft nogle 'kontroltegn' i din buffer på et
tidspunkt, men en blank er #20 og ikke 20.
og
> else if (ord(cStat1[ii])=10) then
kunne også tyde på noget 'snavs'. Som jeg læser 'dokumentationen' få du en
linie ad gangen, og ikke hele dispaly array'et.
Men du må selv forholde dig til om det er 'learning by failing' (Du må godt
sparke mig over benet hvis jeg er for grov, men jeg sidder i Gladsaxe, så
du skal have meget lange ben:).

Back to business, her er et par sentenser om array's og strenge'.
Pascal string's er så snedigt opbygget, så de har en indbygget længde.
I 'gamle' dage, da en streng var max 255 (=Shortstring), kunne man finde
længden som String[0].
Så kom det her C-uhyre ind i billedet, hvor der ikke eksisterer en
længdeangivelse - længden er bestemt ved at tælle op indtil det første #0.
Derfor er C så dårlig til strengoperationer - hvis man skal 'lægge' to
strenge sammen skal man intent have en slags dobbelt loop osv.
For ikke at snakke om hvis 'programmøren' har glemt trailing #0, så
fortsætte C koldt og kynisk derudad uanset om det er hukommelse til
kode,data,stak,heap osv. (Hvem sagde AV?).

På et tidspunkt D1/D2? blev der så lavet nogle tilføjelser til at håndtere
det her C-fænomen.

Det ene er PChar, der er en pointer til et array .. of char, med tilhørende
funktioner, lad os kalde dem Str*, eksempelvis StrCopy osv..

En af de snedige ting (synes jeg) er at array[0..Længde] implicit *også* er
en PChar. I og med offset er 0, er længden den faktiske længde af data, og
den ekstra er #0. Det snedige ligger i at man ikke skal forholde sig til om
man skal lægge en til eller trække fra osv.

Og 'Enter the strings'.
Her har de squ rent ud sagt været geniale. Kort fortalt er de 'nye' strings
internt opbygget som:
Længde + array + #0.
Det betyder at 'vi' kan benytte vores effektive streng håndtering, det med
#0 sker automatisk.
Det snedig er, at hvis vi skal kalde noge C, sætter vi pointeren til at pege
på 'array' delen, så er det automatisk en C-streng i eks. DLL'en.

Hmm.. kommer lige i tanke om at vi har det her 'indernet' - så jeg fandt
lige en side til inspiration:
<http://www.sddug.slctnet.com/pres_e.htm>
Der står det hele, så jeg kunne have sparet tid.

Med det her in mente, og husk lige at vi gemmer 'unicode' til sidst, og at
vi forholder os til hvordan det *burde* være jfr. dokumentationen.

* Din printStatus rutine.
Som jeg læser det, får du en færdiglavet C-streng i bufferen samt et
linienummer.

Jeg fandt lige en anden til dig her:
<http://www.martinstoeckli.ch/delphi/delphi.html>
Kig lige over 'Sto_GetTempPath' - the beauty part:
..... you can simply assign the PChar to a String. In Delphi....

Ud fra det ville din procedure kunne klares med:
procedure Display_Status (Cstat1: PChar; line : Integer);
//Bemærk jeg har pillet VAR ud, da PChar er en pointer.
   Case line of
        1:
        begin
          frmMain.lblDisp1.Caption := Cstat1;
          frmMain.lblDisp1.Update;
        end;
osv....
Ikke noget ekstra fikumdik osv. men stadig ikke unicode.

* din checkStopList rutine.
Stort set den samme suppe, men her er det *dig* der skal allokere
hukommelsen. Altså:
(Husk lige det der med strings og arrays)

var
StatusCode : String ;

function OfflineAutoCode (RetAutCode : PChar) : Integer;
begin  //OfflineAutoCode
  StatusCode := frmMain.LaesKommPFil(KommPOfflineAutCode,6);
  try
    //Hvis svaret er ¥¥¥¥¥¥ er der endnu intet svar
    if (StatusCode='¥¥¥¥¥¥') then
    begin
      StatusCode   := '            ';
      //Jeg returnere 12 blanke.
      RetAutCode := PChar(StatusCode);
osv..
Bemærk at også her er VAR pillet ud jfr. C erklæringen. Men som nævnt
tidligere kan det sagtens være en pointer til en pointer til en poin....,
den eneste der kan afklare det er *programmøren* af DLL-filen. Der er noget
der kunne tyde på, at han er afgået ved døden og har taget kildeteksten med
i krematoriet.

Nå ok, jeg lovede vist at ævle om det der unicode.
Problemet er, at vi befinder os i en transformations fase. Det bedste ville
være hvis Codegear kunne lave en {$unicode on}, og så ville alt være
unicode. Men det kan man ikke bare gøre, så ødelægger man eksisterende
programmer.
Man (Borland/Codegear) har så indført WideStrings og WideChars, der mere
eller mindre understøtter unicode.

Og her Michael - kommer 'the old man' til kort. Som nævnt har jeg ikke haft
brug for Widestrings og Widechars, så jeg aner simpelthen ikke om de samme
ting gør sig gældende. Her må du enten prøve dig frem eller finde nogen der
ved noget om det.

Med hensyn til unicode i C-dll'en, kan jeg komme med et kvalificeret gæt:
Jeg kunne forestille mig, at 'man' har brugt en compiler, der 'automagisk'
jfr. ovenstående behandler alle 'chars' som unicode, men der skal vi igen
have fat i den der 'ghost' for at vide hvordan, og med hvad, den er
kompileret.

Men det kunne være en ganske god forklaring på forvirring og uvidenhed.

Jeg ved ikke om vi kommer længere, men om ikke andet har vi da haft lidt
'julelæsning'.

--
Med venlig hilsen
Stig Johansen

Stig Johansen (15-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 15-12-07 19:17

Nå, jeg 'kom til' at tænde for min WindowsPC med D7.
Nej det passer ikke, det var fordi jeg blev nysgerrig over det her Widechar.

Jeg lavede et lille fedtemadsprogram til at tjekke diverse ting.
Så nu kan jeg komme med kvalificeret input i stedet for min hukommele.

Stig Johansen wrote:
> Michael Vilhelmsen wrote:
>> Det irritere mig bare helt vildt, at:
>>
>> - Oplysningen siger 8 bits char 0 termineret

Korrekt men lad os antage, det er kompileret med '16-bits' understøttelse,
sådan lidt ligesom vores char og widechar.

>> - Jeg kan kun få det til at virke med 16 bits char.

Det tyder på ovenstående, men at dokumentationen ikke er opdateret.

>> - At informationen fra vores leverandør er SÅÅ informativ.

Enig, men som Bjarne ude fra KMD plejer at sige: 'Det giver
kompetanceforøgelse' (sarkastisk udtryk for spild af tid).

>> - At det virker uden jeg helt ved hvorfor.

Ja, det er jo så issuet, virker det eller virker det ikke?


> * Din printStatus rutine.
> Ud fra det ville din procedure kunne klares med:
> procedure Display_Status (Cstat1: PChar; line : Integer);
> //Bemærk jeg har pillet VAR ud, da PChar er en pointer.

Ifølge mine undersøgelser kan du definere den som:
procedure Display_Status (Cstat1: PWideChar; line : Integer); cdecl ;
Bufferen bliver leveret fra dll'en, så hvis den er korrekt)programmeret), er
den klar til brug.


> Case line of
> 1:
> begin
> frmMain.lblDisp1.Caption := Cstat1;

Det er afprøvet. Du direkte assigne en PWideChar til Caption's, lines i memo
o.lign.
Problemet er, at VCL'et ikke understøtter unicode, det kommer først med en
version engang til næste år.
Det betyder at du kun kan bruge 'Table 0' uden at miste data. Men 'Table 0'
er i princippet ISO8859-1, så det betyder normalt ikke noget her i Europa.
Jeg læste fra en edit, over i Widestring,Widechar og tilbage igen.
Det omtalte 'kors' x2020 skulle naturligvis med i spillet.
Det bliver vist som '|' i kontrollerne, men hvis man holder musen over under
debug, bliver den vist korrekt i 'den gule box' (Er det der du har set det
engang?).

> var
> StatusCode : String ;
Ret det til
AutoCode : WideString ;
(Der må have været en bitfejl i den organiske RAM siden jeg kalde det
status).

> function OfflineAutoCode (RetAutCode : PChar) : Integer;

Ret den til
function OfflineAutoCode (VAR RetAutCode : PWideChar) : Integer; cdecl;
jfr. dine erfaringer skal der nok være en VAR, så det bliver en pointer til
en pointer.

> begin  //OfflineAutoCode
> StatusCode := frmMain.LaesKommPFil(KommPOfflineAutCode,6);
Ret det til
AutoCode := frmMain.LaesKommPFil(KommPOfflineAutCode,6);

> try
> //Hvis svaret er ¥¥¥¥¥¥ er der endnu intet svar
> if (StatusCode='¥¥¥¥¥¥') then
Ret det til
if (AutoCode='¥¥¥¥¥¥') then
(Er det der ¥ en reminisens fra DOS tiden? , jeg får helt mareridt over det
der ¥, der var et dansk Ø for 20 år siden. GÅ VÆK CP437!)

> begin
> StatusCode   := '            ';
Ret det til
AutoCode   := ' '; (præcis 6 blanke)

> //Jeg returnere 12 blanke.
Ret det til
//Jeg returnerer 6 _unicode_ blanke.

> RetAutCode := PChar(StatusCode);
Ret det til
RetAutCode := PWideChar(AutoCode);

Nu undrer du dig garanteret over at jeg 'genindfører' cdecl i stedet for din
safecall. Det er fordi du har 2 fejl, som din safecall 'redder' dig ud af.
Det at fejlene er 'reddet' medfører ikke garanti mod følgefejl eller
memoryleaks.

Fejlen i din Display_Status er, eller har været, at du har lavet længden en
for meget. Det betyder, at hvis du læser nr. 21 læser du ud over bufferen
fra c-dll'en(=A/V). Jeg kan se at du stopper ved Ord()=0, er det noget du
har tilføjet senere?

Fejlen i din OfflineAutoCode er, at du ikke rigtig bruger Widechar men i
stedet 'dobbelt' almindelig streng.
Principielt bliver længden det samme MEN men, og det er jeg ked af jeg ikke
tænkte på noget før, en almindelig streng afsluttes med 8-bits 0 (x00) men
Widestrings afsluttes med 16-bits 0 (0x0000). Det betyder at du
'fysisk'afleverer 13 bytes (12 tegn+x00) og ikke 14 bytes (6 unitegn +
x0000).
Når c-dll'en prøver at læse byte 14 er vi ude i en A/V eller lignende. Hvad
værre er, at hvis byte 14 ikke er x00, fortsætter c-dll'en højst
sandsynligt indtil den finder en x0000 - eller går død.

--
Med venlig hilsen
Stig Johansen

Stig Johansen (18-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 18-12-07 06:25

Follow up.

Stig Johansen wrote:
> Stig Johansen wrote:
>> Michael Vilhelmsen wrote:
>>> Det irritere mig bare helt vildt, at:
>>>
>>> - Oplysningen siger 8 bits char 0 termineret
>
> Korrekt men lad os antage, det er kompileret med '16-bits' understøttelse,
> sådan lidt ligesom vores char og widechar.

'The sun is rising'.
Faldt lige over denne her:
<http://cplus.about.com/od/glossar1/g/chardefinition.htm>

<klip>
Definition: A char is a type of variable that holds a character in C and
C++. On Win 32, unless explicitly defined as Unicode, a char is 8 bits,
which is the same size as a byte.
</klip>

Bemærk: 'unless explicitly defined as Unicode'.
Dvs. der *er* muighed for at definere en char som unicode.
'Vi' andre ville nok have kaldt det hhv wchar og char, men sådan er c-folket
ikke - tsk tsk.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (17-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 17-12-07 08:58

Stig Johansen wrote on 14-12-2007 :
> Michael Vilhelmsen wrote:
>
>> After serious thinking Stig Johansen wrote :
>>> Jeg ved egentlig ikke rigtig hvor meget vi skal gøre ud af det her - du
>>> skriver det virker, så det er måske 'godt nok'. Jeg ville måske føle mig
>>> utryg ved ikke at vide *hvorfor* det virker. Men igen det er de sataner,
>>> der har leveret DLL'en, der sidder på oplysningerne, vi andre kan kun
>>> 'prøve os frem'.
>>
>> Det samme her.
>>
>> Det virker.
>> Det er det primære.
>> Så kan det komme i produktion.
>>
>> Det irritere mig bare helt vildt, at:
>>
>> - Oplysningen siger 8 bits char 0 termineret
>> - Jeg kan kun få det til at virke med 16 bits char.
>> - At informationen fra vores leverandør er SÅÅ informativ.
>> - At det virker uden jeg helt ved hvorfor.
>
> Jeg prøver lige at kommentere lidt fra de forskellige svar i denne her, der
> er ingen garanti for struktur.
>
>> Det jeg forsøger at lave er kommunikation med en kreditkorts terminal.
>
> He he, den havde jeg kuret fra starten. Når 'the old man', der bla har lavet
> banksystemer i 10 år ser ord som 'PBS','Dankort' osv. Netop derfor er det
> vigtig (synes jeg) at det er 'korrekt'.
>


Jeg kigger lige nærmere på al din skrift en gang efter weekenden.
Har pt. et par opgaver der lige skal gøres færdig - Så det må lige vente.

Kort - Det har kørt de sidste 3½ år som det er nu (minus den nye rutine).
Det har aldrig givet problemet.
Ikke andet end det man kan forvente, når hardware går i udu, forbindelse til PBS ikke er der etc.

Så jeg er faktisk ikke bange for, at det er "fundamentalt forkert" (var det ikke det ord du brugte?)


Jeg er mere interesseret i, om jeg kan finde noget mere logik end det jeg har nu.
Jeg har tidligere læst en del om dette - Og det jeg læste, og det jeg gør for at få det til at virke - Ja det er ikke helt det samme.
Så min forvirring har været / er stor.


Men en gang efter weekenden tager jeg lige en kigger mere - Og sammen med denne prøver jeg noget af det, som du har beskrevet her.

Jeg vender tilbage med information snarest.

Mcihael

> Du skal lige abstrahere fra det der 'unicode', jeg vil kommentere ud fra
> 'normale' tegn. Så kan jeg bedre selv forstå hvad jeg skriver. Så til ta'r
> vi 'unicode' delen.
>
> Ovre fra 'mail' en:
>> Code er en '\0' termineret ascii (8-bit) streng med længden 6+1 bytes, som
>> applikationen 'ejer'.
>
> Mailen er kort, men her ligger rent faktisk svaret på et af de spørgsmål jeg
> har stillet.
> (Hov, det er ekstremt vigtigt at vide hvor hukommelsen til 'Code' bliver
> allokeret.)
> Det er forskellige ordvalg, men applikationen 'ejer' betyder, at det er
> *dit* program, der er ansvarlig for hukommelsen. Det er også det normale
> ved brug af dll'er.
> Skal vi fortolke denne her ordret er ækvivalenten array[0..6] of char.
>
> Lad mig lige hoppe over til din 'print'..
>> void printStatus( const char cStat[21], unsigned int line ); og
>> with a maximum length of 21 incl. '\0'.
> Denne her er array[0..20] of char og ikke [0..21].
> Læg mærke til *incl* '\0', det giver 20 tegn på display'et.
>
> Når jeg ser denne her:
>> if (Ord(cStat1[ii])>20) and (Ord(cStat1[ii])<SkilleTegn) then
> Før jeg indtrykket af, at du har haft nogle 'kontroltegn' i din buffer på et
> tidspunkt, men en blank er #20 og ikke 20.
> og
>> else if (ord(cStat1[ii])=10) then
> kunne også tyde på noget 'snavs'. Som jeg læser 'dokumentationen' få du en
> linie ad gangen, og ikke hele dispaly array'et.
> Men du må selv forholde dig til om det er 'learning by failing' (Du må godt
> sparke mig over benet hvis jeg er for grov, men jeg sidder i Gladsaxe, så
> du skal have meget lange ben:).
>
> Back to business, her er et par sentenser om array's og strenge'.
> Pascal string's er så snedigt opbygget, så de har en indbygget længde.
> I 'gamle' dage, da en streng var max 255 (=Shortstring), kunne man finde
> længden som String[0].
> Så kom det her C-uhyre ind i billedet, hvor der ikke eksisterer en
> længdeangivelse - længden er bestemt ved at tælle op indtil det første #0.
> Derfor er C så dårlig til strengoperationer - hvis man skal 'lægge' to
> strenge sammen skal man intent have en slags dobbelt loop osv.
> For ikke at snakke om hvis 'programmøren' har glemt trailing #0, så
> fortsætte C koldt og kynisk derudad uanset om det er hukommelse til
> kode,data,stak,heap osv. (Hvem sagde AV?).
>
> På et tidspunkt D1/D2? blev der så lavet nogle tilføjelser til at håndtere
> det her C-fænomen.
>
> Det ene er PChar, der er en pointer til et array .. of char, med tilhørende
> funktioner, lad os kalde dem Str*, eksempelvis StrCopy osv..
>
> En af de snedige ting (synes jeg) er at array[0..Længde] implicit *også* er
> en PChar. I og med offset er 0, er længden den faktiske længde af data, og
> den ekstra er #0. Det snedige ligger i at man ikke skal forholde sig til om
> man skal lægge en til eller trække fra osv.
>
> Og 'Enter the strings'.
> Her har de squ rent ud sagt været geniale. Kort fortalt er de 'nye' strings
> internt opbygget som:
> Længde + array + #0.
> Det betyder at 'vi' kan benytte vores effektive streng håndtering, det med
> #0 sker automatisk.
> Det snedig er, at hvis vi skal kalde noge C, sætter vi pointeren til at pege
> på 'array' delen, så er det automatisk en C-streng i eks. DLL'en.
>
> Hmm.. kommer lige i tanke om at vi har det her 'indernet' - så jeg fandt
> lige en side til inspiration:
> <http://www.sddug.slctnet.com/pres_e.htm>
> Der står det hele, så jeg kunne have sparet tid.
>
> Med det her in mente, og husk lige at vi gemmer 'unicode' til sidst, og at
> vi forholder os til hvordan det *burde* være jfr. dokumentationen.
>
> * Din printStatus rutine.
> Som jeg læser det, får du en færdiglavet C-streng i bufferen samt et
> linienummer.
>
> Jeg fandt lige en anden til dig her:
> <http://www.martinstoeckli.ch/delphi/delphi.html>
> Kig lige over 'Sto_GetTempPath' - the beauty part:
> .... you can simply assign the PChar to a String. In Delphi....
>
> Ud fra det ville din procedure kunne klares med:
> procedure Display_Status (Cstat1: PChar; line : Integer);
> //Bemærk jeg har pillet VAR ud, da PChar er en pointer.
>    Case line of
>         1:
>         begin
>           frmMain.lblDisp1.Caption := Cstat1;
>           frmMain.lblDisp1.Update;
>         end;
> osv....
> Ikke noget ekstra fikumdik osv. men stadig ikke unicode.
>
> * din checkStopList rutine.
> Stort set den samme suppe, men her er det *dig* der skal allokere
> hukommelsen. Altså:
> (Husk lige det der med strings og arrays)
>
> var
> StatusCode : String ;
>
> function OfflineAutoCode (RetAutCode : PChar) : Integer;
> begin  //OfflineAutoCode
>   StatusCode := frmMain.LaesKommPFil(KommPOfflineAutCode,6);
>   try
>     //Hvis svaret er ¥¥¥¥¥¥ er der endnu intet svar
>     if (StatusCode='¥¥¥¥¥¥') then
>     begin
>       StatusCode   := '            ';
>       //Jeg returnere 12 blanke.
>       RetAutCode := PChar(StatusCode);
> osv..
> Bemærk at også her er VAR pillet ud jfr. C erklæringen. Men som nævnt
> tidligere kan det sagtens være en pointer til en pointer til en poin....,
> den eneste der kan afklare det er *programmøren* af DLL-filen. Der er noget
> der kunne tyde på, at han er afgået ved døden og har taget kildeteksten med
> i krematoriet.
>
> Nå ok, jeg lovede vist at ævle om det der unicode.
> Problemet er, at vi befinder os i en transformations fase. Det bedste ville
> være hvis Codegear kunne lave en {$unicode on}, og så ville alt være
> unicode. Men det kan man ikke bare gøre, så ødelægger man eksisterende
> programmer.
> Man (Borland/Codegear) har så indført WideStrings og WideChars, der mere
> eller mindre understøtter unicode.
>
> Og her Michael - kommer 'the old man' til kort. Som nævnt har jeg ikke haft
> brug for Widestrings og Widechars, så jeg aner simpelthen ikke om de samme
> ting gør sig gældende. Her må du enten prøve dig frem eller finde nogen der
> ved noget om det.
>
> Med hensyn til unicode i C-dll'en, kan jeg komme med et kvalificeret gæt:
> Jeg kunne forestille mig, at 'man' har brugt en compiler, der 'automagisk'
> jfr. ovenstående behandler alle 'chars' som unicode, men der skal vi igen
> have fat i den der 'ghost' for at vide hvordan, og med hvad, den er
> kompileret.
>
> Men det kunne være en ganske god forklaring på forvirring og uvidenhed.
>
> Jeg ved ikke om vi kommer længere, men om ikke andet har vi da haft lidt
> 'julelæsning'.

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Stig Johansen (18-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 18-12-07 04:49

Michael Vilhelmsen wrote:

> Så jeg er faktisk ikke bange for, at det er "fundamentalt forkert" (var
> det ikke det ord du brugte?)

Det håber jeg ikke jeg har skrevet - det er i hvert fald ikke meningen.
Jeg har kun påpeget at du har(haft) en char/widechar for meget - samt at du
ikke bruger cdecl.

> Jeg er mere interesseret i, om jeg kan finde noget mere logik end det jeg
> har nu.

Jeg har givet input/løsning til noget mere logisk i mit forrige indlæg, hvis
du er interesseret vil jeg gerne 'wrappe' det op i hele funktioner, så du
ikke behøver at plukke ud fra de her indlæg.

> Jeg har tidligere læst en del om dette - Og det jeg læste, og det
> jeg gør for at få det til at virke - Ja det er ikke helt det samme. Så min
> forvirring har været / er stor.

Jeg forstår dig, og jeg føler med dig. Den viden jeg har er ikke noget jeg
har læst mig til, det tvivler jeg på man kan.
Næh - den kommer fra gud ved ikke hvor mange dage/aftener/nætter med at
sidde og rive sig i håret mens deadline nærmer sig. Der var ikke noget der
hed internet osv. så det var virkelig 'lerning by failing' eller 'learning
by trying'. Da jeg skrev 'learning by failing', var det fordi jeg kom til
at tænke på mig selv, da jeg sad alene, altså ikke fysisk alene, men alene
forstået på den måde at der ikke var nogen at spørge.
Altså det var ingen kritik, jeg fik bare indtrykket af, at du også har
siddet mere eller mindre alene med problemet 'dengang'.

> Men en gang efter weekenden tager jeg lige en kigger mere - Og sammen med
> denne prøver jeg noget af det, som du har beskrevet her.

Igen - hvis du er interesseret vil jeg gerne wrappe det op til 'færdige'
funktioner.

> Jeg vender tilbage med information snarest.

Det behøver du ikke, bare sørg for du ikke går julen i møde med 'uløste'
problemer.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (18-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 18-12-07 15:33

>
>> Jeg vender tilbage med information snarest.
>
> Det behøver du ikke, bare sørg for du ikke går julen i møde med 'uløste'
> problemer.

Ingen uløste ender her.

Programmet som har kørt upåklageligt i 3½ år er det som er ude.

Dette kommer ikke ud forløbigt alligevel - Bare ved at forberede mig i god tid

Mht. wrapning af funktioner - Hvis det ikke er for meget forlangt vil jeg da gerne se det.

Michael


PS.

Men lad være at stresse - Det er der nok af i denne juletid.
Hold dig nu en god og fortjent juleferie - Så tager vi det hele efter jul / nytår, hvor min tid alligevel er lidt bedre.

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://www.mesnews.net



Stig Johansen (19-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 19-12-07 05:59

Michael Vilhelmsen wrote:

> Mht. wrapning af funktioner - Hvis det ikke er for meget forlangt vil jeg
> da gerne se det.

Hehe - kommunikation er en svær en - 'wrap up' er det udtryk vi brugte i HP
når vi afsluttede møder. Opsummering er måske et bedre ord.

_Løsningerne_ ligger spredt undervejs i de forskellige indlæg, og jeg har
sendt nogle links til noget meget svært fordøjelig læsning, så 'wrap up' er
'bare' en renskrift af 'facitlisten'.

> Men lad være at stresse - Det er der nok af i denne juletid.
> Hold dig nu en god og fortjent juleferie - Så tager vi det hele efter jul
> / nytår, hvor min tid alligevel er lidt bedre.

Ingen stress her, men jeg laver den nok snart - inden jeg glemmer det hele.

--
Med venlig hilsen
Stig Johansen

Stig Johansen (20-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 20-12-07 05:27

Stig Johansen wrote:

> _Løsningerne_ ligger spredt undervejs i de forskellige indlæg, og jeg har
> sendt nogle links til noget meget svært fordøjelig læsning, så 'wrap up'
> er 'bare' en renskrift af 'facitlisten'.

Jeg ved du har travlt med noget andet og det her er mere en 'husker' til mig
selv, men for at få det fuldstændige overblik, mangler 'jeg' oplysning om
den overordnede memoryhåndtering.

Har du ikke en eller anden 'init' funktion, som du kalder som det
allerførste. Her ville man normalt sende en pointer over til noget
Comarea/Workspace eller lign. på en eller anden minimum størrelse?

Noget i stil med:
var
Comarea : packed array [1..1000] of byte.
......
flxInitDll (...,@Comarea,..)

Jeg skal bruge det for at 'gå i dybden' men min forklaring.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (20-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 20-12-07 13:56

Stig Johansen used his keyboard to write :
> Stig Johansen wrote:
>
>> _Løsningerne_ ligger spredt undervejs i de forskellige indlæg, og jeg har
>> sendt nogle links til noget meget svært fordøjelig læsning, så 'wrap up'
>> er 'bare' en renskrift af 'facitlisten'.
>
> Jeg ved du har travlt med noget andet og det her er mere en 'husker' til mig
> selv, men for at få det fuldstændige overblik, mangler 'jeg' oplysning om
> den overordnede memoryhåndtering.
>
> Har du ikke en eller anden 'init' funktion, som du kalder som det
> allerførste. Her ville man normalt sende en pointer over til noget
> Comarea/Workspace eller lign. på en eller anden minimum størrelse?
>
> Noget i stil med:
> var
> Comarea : packed array [1..1000] of byte.
> .....
> flxInitDll (...,@Comarea,..)
>
> Jeg skal bruge det for at 'gå i dybden' men min forklaring.


Lad os se.

OnCreate / OnShow initiere en hel del af mine egne variabler, samt nogle kommunikationsfiler jeg selv bruger.
Noget af det sidste jeg gør i disse rutiner er en initier procedure (lavet af mig selv).

Ser ud som følger:

flxInitCallback(FLX_CALLBACK_STOPLIST,@OfflineAutoCode);
flxInitCallback(FLX_CALLBACK_SET_CARDDATA,@SetCardData);
flxInitCallback(FLX_CALLBACK_PRINT_RECEIPT,@Print_Receipt);
flxInitCallback(FLX_CALLBACK_DISPLAY_STATUS,@Display_Status);
flxInitCallback(FLX_CALLBACK_ABORT,@AbortTrans);
flxInitCallback(FLX_CALLBACK_ADVICEFLAG,@adviceFlag);
flxInitCallback(FLX_CALLBACK_SET_AMOUNT_FEE,@SetAmountFee);
flxInitCallback(FLX_CALLBACK_MENU,@MenuMenu);
flxInitCallback(FLX_CALLBACK_MENURESULT,@SetMenu);


fxlInitCallBack er defineret i flex.pas, som jeg benytter i min USES.

Unit Flex ser lidt sådan ud:



unit flex;

interface

uses
Windows;

Type
FLX_AMOUNT = dword;

STAN = record
data : array[0..2] of byte;
end;

PAN = record
len : byte;
data : array[0..9] of byte;
end;



.......

en masse flere type, const og variabler kommer nu.


procedure flxInitCallback(method_id:Integer; method_ptr:pointer); StdCall ; External 'flxdrv.dll';
function flxConnect(dummy:Integer):Integer; StdCall ; External 'flxdrv.dll';
function flxDisconnect:Integer; StdCall ; External 'flxdrv.dll';
function flxOpen:Integer; StdCall ; External 'flxdrv.dll';
function flxClose:Integer; StdCall ; External 'flxdrv.dll';
function flxCardTransaction (transactionType : Integer;
amount : FLX_AMOUNT;
currencyCode : Integer;
merchantInitiative : byte;
var refno : dword;
var error : Integer) : Integer; StdCall ; External 'flxdrv.dll';

.....

Nogle flere functioner

implementation


end.







Efter initiering gør jeg ikke rigtigt mere.
Andet end at kalde de der forskellige functioner.


Her er noget tekst fra en pdf fil:

5.3 The Flexdriver functions

This section describes the function used to set-up the Flexdriver and initiate routines on the Terminal. . For up to date information consult the latest flex.h file.
Using functions with Visual Basic 6, the WINAPI is using the __stdcall naming convention. The function name preceded by an underscore ( _ ) and followed by an at sign (@) and the size of the
function's arguments in bytes. No case translation is performed.


5.3.1 The flxInitCallback function

This function is used to set-up the Flexdriver with the functions that the ECR uses to print receipt etc.

Synopsis
void flxInitCallback( FLX_CALLBACK methodId, void* methodPtr );

Parameter description
methodId informs the flex-driver on which connection to use the method methodPtr.

The possible values for method_id are:
FLX_CALLBACK_SET_CARDDATA -> function which uses the card number
FLX_CALLBACK_PRINT_RECEIPT -> function to print the receipt
FLX_CALLBACK_DISPLAY_STATUS -> function to display status messages
FLX_CALLBACK_VERSIGCONFIRM -> function which verifies the signature
FLX_CALLBACK_ABORT -> function which aborts the transaction
FLX_CALLBACK_ADVICEFLAG -> function which uses advice flags
FLX_CALLBACK_ADVICELOG -> function to get a copy of terminal datastore operations
FLX_CALLBACK_MENU -> function to display menus on the ECR display
FLX_CALLBACK_MENURESULT -> function to reply to selected menu
FLX_CALLBACK_SET_AMOUNT -> function which delivers the amount
FLX_CALLBACK_SET_AMOUNT_FEE -> ECR calculates the fee in this function
FLX_CALLBACK_GET_AMOUNT_FEE -> Terminal calculates the fee and delivers it in this function
FLX_CALLBACK_GET_BINARY_RECEIPT -> The terminal delivers a binary receipt
FLX_CALLBACK_EARLY_STAN_PAN   -> The terminal delivers transaction stan and pan

Notice that call-back methods must be initiated with flxInitCallback before the rest of the driver's methods can be used. Non of the call-back methods used as argument to flxInitCallback must be
blocking (The functions must return immediately).

Return values None

Example:

flxInitCallback( FLX_CALLBACK_SET_CARDDATA, setCardData );
flxInitCallback( FLX_CALLBACK_PRINT_RECEIPT, printReceipt );
flxInitCallback( FLX_CALLBACK_DISPLAY_STATUS, printStatus );
flxInitCallback( FLX_CALLBACK_ABORT, abortTransaction );
flxInitCallback( FLX_CALLBACK_VERSIGCONFIRM, verSigConfirmation );
flxInitCallback( FLX_CALLBACK_ADVICEFLAG, adviceFlag );
flxInitCallback( FLX_CALLBACK_MENU, showMenu );
flxInitCallback( FLX_CALLBACK_MENURESULT, resultMenu );





Ville gerne have vist dig mere af koden (faktisk hele programmet, hvis det var), men min chef syntes ikke det var "Verdens bedste idé"





Jeg har fundet en flex.h fil.
Syntes du på et punkt efterlyste en sådan:


#ifndef __FLEX_H
#define __FLEX_H


#ifdef __cplusplus
extern "C" { // only need to export C interface if
#endif // used by C++ source code

#ifdef _WIN32
#define DllExport __declspec(dllexport)
#else
#define DllExport
#endif

#define MAX_RECEIPT_SIZE 1600

#ifndef TRUE
#define TRUE 1
#define true TRUE
#endif
#ifndef FALSE
#define FALSE 0
#define false FALSE
#endif

// return values
#define SUCCESS 0x00
#define FAILURE 0x01

// flxConnect return values
#define CONNECT_OK         0x00
#define CONNECT_NO_INIFILE      0x01
#define CONNECT_INIFILE_READ_ERROR   0x02
#define CONNECT_COMPORTINITFAILURE   0x03
#define CONNECT_SW_NOTCOMPATIBLE   0x04
#define CONNECT_TERM_NOT_RESP      0x05
#define CONNECT_COMPORTOPEN      0x06

// Generel flx error values
#define DATALINKERROR            0x07
#define FUNCTION_NOT_POSSIBLE      0x08
#define TIMEOUT_IN_COMMUNICATION   0x09
#define CONNECT_NO_LICENCE 0x0A
#define CONNECT_INTERNAL_ERROR 0x0B

// flxCardTransaction return values when local card
#define LOCALCARD_OK 0x10
#define LOCALCARD_NOT_OK 0x11

// Trace level defines
enum {
   CONF_PARAM = 1,      // Placement of inifile
   CONF_TRACE,      // Enable trace
   CONF_EXTTRACE,      // Enable extensive tracing
   CONF_EXTTRACE_PLUS   // Enable extensive tracing with append
};

// Terminal/ECR communication communication type
enum {
   RS232_COMM = 1,
   ETHERNET_COMM
};

// CALLBACK METHODS
typedef enum {
   FLX_CALLBACK_SET_CARDDATA = 0,
   FLX_CALLBACK_PRINT_RECEIPT,
   FLX_CALLBACK_DISPLAY_STATUS,
   FLX_CALLBACK_ABORT,
   FLX_CALLBACK_EXTCARDCONFIRM,
   FLX_CALLBACK_VERSIGCONFIRM,            // 5
   FLX_CALLBACK_ADVICEFLAG,
   FLX_CALLBACK_SET_AMOUNT,            // send amount to terminal from ecr
   FLX_CALLBACK_SET_AMOUNT_FEE,         // send fee to terminal from ecr
   FLX_CALLBACK_GET_AMOUNT_FEE,         // receive fee from terminal to ecr
   FLX_CALLBACK_STATUSTRACE,            // 10
   FLX_CALLBACK_STATETRACE,
   FLX_CALLBACK_ADVICELOG,
   FLX_CALLBACK_MENU,
   FLX_CALLBACK_MENURESULT,
   FLX_CALLBACK_GET_BINARY_RECEIPT,      // 15
   FLX_CALLBACK_EARLY_STAN_PAN,
   FLX_CALLBACK_BREAK_IP,
} FLX_CALLBACK;

// Abort callback return values
#define OPERATORWISHTOABORT         0x01
#define OPERATORDONOTWISHTOABORT   0x02

// Receipt callback return values
#define RECEIPT_OK            0x01
#define RECEIPT_NOTOK            0x00

// verSigConfirmation callback return values
// used in resultmenu
#define SIGNATURE_OK            0x01
#define SIGNATURE_NOTOK            0x00
#define SIGNATURE_NOTKNOWNYET      0x02

// resultMenu
#define MENU_RESULT               0x03

// Carddata callback return values
#define CARDNUMBER_OK            0x01
#define CARDNUMBER_OK_CONFIRM 0x03 // External card confirm ...
#define CARDNUMBER_NOTOK         0x00

// cardType values
#define PBS_CARD               0x00
#define OTHER_CARD               0x01


// TRANSACTION METHODS
typedef enum {
   FLX_TRANS_PURCHASE = 0,               // Debit transaction
   FLX_TRANS_REFUND,                  // Credit transaction
} FLX_TRANSTYPE;

// ERROR CODES
enum {
   ERR_UNKNOWN = 0x00010000,
   ERR_TERM_NOT_READY,
   ERR_NO_CONNECTION,
   ERR_NO_RECEIPT,
   ERR_SW_NOTCOMPATIBLE,
   ERR_NO_LICENCE
};

// ADMINISTRATION FUNCTIONS
typedef enum{
ADMIN_ENDOFDAY = 1,
ADMIN_ENDOFDAYLOG,
ADMIN_REPORT_TERMINALREPORT,
ADMIN_REPORT_TOTALS,
ADMIN_REPORT_LOG,
ADMIN_REPORT_OLDLOG,
ADMIN_LASTRECEIPT,
ADMIN_UNLOCK_RECEIPT,
ADMIN_CLOCKSYNCPBS,
ADMIN_CLOCKSYNCPOINT,
ADMIN_SENDLOG,
ADMIN_CLEARDATASTORE,
ADMIN_DOWNLOADPROGRAM,
ADMIN_DOWNLOADPARAM,
ADMIN_DOWNLOADPAN,
ADMIN_DOWNLOADTLCMDB,
ADMIN_RESTORETLCMDB,
ADMIN_CONTRASTUP,
ADMIN_CONTRASTDOWN,
ADMIN_RESTARTTERMINAL,
ADMIN_EJECTCARD,
ADMIN_MSC,
ADMIN_MAX,            // last entry
} FLX_ADMIN_FUNCTION;

#define ADMIN_GET_DC_PROPERTIES_STAN   0x80
#define ADMIN_GET_DC_PROPERTIES_PAN      0x81


// CURRENCY CODES
typedef enum {
   DKK=208,      // DK Kroner
   ISK=352,      // IS Kroner
   JPY=392,      // JP Yen
   NOK=578,      // N Kroner
   SEK=752,      // S Kroner
   CHF=756,      // SW Francs
   GBP=826,      // GB Pound
   USD=840,      // US Dollar
   EUR=978,      // Euro
} CURR_CODES;

typedef enum {
   MI_PIN = 0,
   MI_OFFLINE = 0x60,
   MI_FORCED_PIN = 0x81,
   MI_FORCED_SIGNATURE = 0x82,
} FLX_MI;

#ifndef WIN32
typedef unsigned long FLX_AMOUNT;   // Amount must be 4 bytes.
#else
typedef unsigned int FLX_AMOUNT;   // Use 32 bit Windows
#endif


/* BINARY RECEIPT INFO STRUCT RETURNED BY FLX_CALLBACK_GET_BINARY_RECEIPT */

#ifndef _TIME_T_DEFINED
#ifndef BUILDING_LINUX_DLL
typedef long time_t; /* time value */
#endif
#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
#endif

typedef struct {
   time_t      gmtime;               // Unix time stamp
FLX_AMOUNT   total;               // total amount in smallest currency unit
   FLX_AMOUNT   extra;               // extra -
   FLX_AMOUNT   fee;               // fee -
int       currency;            // Currency code (208=DKK, 978=EUR, 840=USD etc.)
   int       Stan;               // PBS reference number converted from BCD code
int       PSAM_Creator;         // PSAM #
   int       PSAM_ID;            // PSAM ID #
   int       MTI;               // PBS apacs transaction code
   int       Asw1Asw2;            // PSAM retur code (see OTRS specification)
   int       ActionCode;            // Transaction result code
   int         refNr;               // Transaction reference number passed from user

   char      pbsResult;            // PBS Transaction result
   char    CvmStatus;            // Cardholder verification method (eg. if signature required) see EMV specs.
   char    CardDataSource;         // Magnetic- or chip card
   char    TR;                  // Transaction request
   char    nota;               // True if signature on receipt
   char    copy;               // True if receipt copy
char    mt;                  // EMV decline code see EMV specification
   char    psn;               // EMV pan sequence number see EMV specification
   char    lenPAN;               // Length of PAN
char    lenAID;               // Length of AID

   char    PAN[10];            // Primary account number BCD code
   char      AID[16];            // EMV application ident.
   char    ATC[2];               // EMV value see EMV specification
   char    AED[3];               // EMV value see EMV specification
   char    ARC[2];               // EMV value see EMV specification
char    PosEntryMode[3];      // Transaktionen information see OTRS and EMV specification.

int         number;               // Merchant PBS number
   char    authorizationCode[6+1];   // PBS authorization code as string
   char    CardName[16+1];         // Card name as string (+1 indicate string termination '\0')
   char    TermIdent[8+1];         // Terminal ID string
char    name[18+1];            // Merchant name as string
char    city[16+1];            // Merchant city as string
char    address[24+1];         // Merchant address as string
char    zip_code[8+1];         // Merchant zip code as string
char    phone[24+1];         // Merchant phone number as string
char    cvr[12+1];            // Merchant CVR number as string

} ReceiptStruct;


/* Structs used by the flxGetDCproperties callback method   */

typedef struct {
unsigned char len;
unsigned char data[10];
} PAN;

typedef struct {
   unsigned char data[3];
} STAN;

typedef union {
   STAN   stan;
   PAN   pan;
} STAN_PAN;

typedef struct {
   STAN      refStan;         // unique psam transaction identifier
   FLX_AMOUNT   amount;
   int         currc;            // curreccy code
   int         curre;            // currency exponent
   char      DTHR[5];         // PBS timestamp year, month, day, hour, minute
} DC_RESULT;



/*
   These CALLBACK FUNCTIONS are defined and coded in the ECR software
   They are documented here for your convinience
   These functions must be implemented by the ECR when mandatory or when used
   (e.i. activated and defined using flxInitCallback).
*/
/*
   Function:   pcbPrintReceipt
            printReceipt prints a formatted receipt or report.

   Prototype:   int printReceipt(unsigned int receipt_status, const char* cText);

   Input:      receipt_status   - 0x01 if there are missing segments (e.g. during ADMIN_REPORT_LOG)
                         0x00 if it is the last/whole segment (all transaction receipts).

            cText         - receipt text coded as ISO 8859-15 and 0 terminated.
                         maximum length in 1000 characters incl. '\0'.
                         If a larger text must be printed divided in smaller segments.

   Output:                  -
   Return:      RECEIPT_OK   - receipt printed OK
         RECEIPT_NOTOK   - receipt NOT printed OK


*/
/*
   Function:   pcbAbort
            printAbort asks if operator whish to abort currect transaction.
            During transactions the flex-driver repeatedly calls the abortTransaction function.
            Notice that even though the ECR tries to abort a Transaction, it might not be aborted.
            It is the Terminal that decides if the Transaction is aborted, or not.
            This function must be implement

   Prototype:   int pcbAbort (void);

   Input:      -

   Output:      -               -
   Return:      OPERATORWISHTOABORT         - Abort
            OPERATORDONOTWISHTOABORT   - do not abort


*/
/*
   Function:   pcbSetCarddata
            pcbSetCarddata gives cardnumber cardtype and crc (card reconcilliation counter id).
            Can be used by the ECR to reject certain types of credit cards,
            e.g. if a customer wishes to get some cash together with the purchased item,
            then the ECR should ensure that the swiped card isn't a credit card.

   Prototype:   int setCarddata(const char *cPan, int cardtype);

   Input:      *cPan      - pointer to 8 first numbers in cardnumber(pan),crc in ascii
                      (e.g. 54130347,1 (1 is dankort))
            cardtype   - PBS_CARD      - eg. Dankort
                      OTHER_CARD   - eg. Local card

   Output:      -
   Return:      CARDNUMBER_OK         - cardnumber ok
            CARDNUMBER_OK_CONFIRM   - cardnumber (e.g. local card) OK
            CARDNUMBER_NOTOK      - cardnumber nor ok


*/
/*
   Function:   pcbDisplayStatus
            pcbDisplayStatus gives an ascii status line

   Prototype:   void pcbDisplayStatus(const char cStat[21], unsigned int line);

   Input:      cStat[]      - pointer 20 char ascii string plus '\0' termination coded as ISO 8859-15
            line      - suggested status line number (1-4)

   Output:      -
   Return:      -

*/
/*
   Function:   pcbVerSigConfirm
            pcbVerSigConfirm asks for signature approval on a signaturetransaction.
            E.g. it could be implemented so the operator e.g. presses 'F1' for approval and 'F2' for rejected.
            The PSAM decides if this functionality is used or not.
            If it is not called and the transaction is approved, both receipts will be sent from the terminal straight away.
            If the signature afterwards seems fake, the operator must run a refund.

   Prototype:   int pcbVerSigConfirm (void);

   Input:      -
   Output:      -
   Return:      SIGNATURE_OK
            SIGNATURE_NOTOK
            SIGNATURE_NOTKNOWNYET

*/
/*
   Function:   pcbAdviceFlag
            pcbAdviceFlag signals that balancing/endofday routine is nessesary
            Meaning that the ECR must not be able to run further transactions before the endofday routine is run and approved.
            This function is mandatory to implement


   Prototype:   void pcbAdviceFlag (void);

   Input:      -
   Output:      -
   Return:      -

*/
/*
   Function:   pcbSetAmount
            pcbSetAmount sets the transaction amount
            If this function isn't initialised in the flxInitCallback function,
            then the amount given in the flxCardTransaction is used.

   Prototype:   FLX_AMOUNT pcbSetAmount(void);

   Input:      -
   Output:      -
   Return:      FLX_AMOUNT - the transaction amount (always positive)
                      amount in lowest currency denomination (e.g. øre).

*/
/*
   Function:   pcbGetAmountFee
            pcbGetAmountFee gives the fee calculated in the terminal.

   Prototype:   void pcbGetAmountFee(FLX_AMOUNT fee);

   Input:      fee   - fee
   Output:      -
   Return:      -

*/
/*
   Function:   pcbSetAmountFee
            pcbSetAmountFee gives the fee calculated in the terminal.

   Prototype:   FLX_AMOUNT pcbSetAmountFee(void);

   Input:      -
   Output:      -
   Return:      FLX_AMOUNT - the transaction fee (always positive) calculated by the ECR
                      amount in lowest currency denomination (e.g. øre).
                      if used in with pcbGetAmountFee, it overrules the terminal fee.

*/
/*
   Function:   pcbStatusTrace
            pcbStatusTrace

   Prototype:   void pcbStatusTrace (const char *trace);

   Input:      -
   Output:      -
   Return:      -
*/
/*
   Function:   pcbStateTrace
            pcbStateTrace

   Prototype:   void pcbStateTrace (int state);

   Input:      -
   Output:      -
   Return:      -
*/
/*
   Function:   pcbAdviceLog
            pcbAdviceLog sends copies of datastore operations to the ECR.
            The transaction time is increased by approx half a second when using this function.

   Prototype:   void adviceLog (unsigned int len, const unsigned char* data);

   Input:      len      - length of advice data
            *date   - pointer to advise data
   Output:      -
   Return:      -
*/
/*
   Function:   pcbMenu
            pcbMenu is currently used to display information to the operator.
            E.g. if or if not an EMV card is placed correctly in the terminal (command=0).
            The function is also used for the operator to choose between EMV applications
            in correlation with refund transactions (10 <= command >= 1).

   Prototype:   void pcbMenu(unsigned char command, int timeout, unsigned char lines, const char menus[][21]);

   Input:      command      - command (or suggested line to display).
                      0: EMV card inserted correct?
                      1-10: suggested menu to display.
            timeout      - timeout value that the ECR must answer whihin (using pcbMenuResult)
            lines      - number of lines in menu (max. 10)
            menus[][]   - menulines in ascii from 1 to 10
                      each line is 20 char plusterminating '\0'.
   Output:      -
   Return:      -
*/
/*
   Function:   pcbMenuResult
            pcbMenuResult is called repetitively (like abort), to verify the choice made by the operator,
            when a menu is displayed on the ECR screen.

   Prototype:   void pcbMenuResult(char *result);

   Input:      *result   - pointer to result holding selected line in menu
   Output:      -
   Return:      0 - the answer isn’t known yet (the operator hasn’t pressed a key) and no timeout has occurred.
            1 - the chosen menu point must be entered in the result variable
             e.g. *result = 1 if first menu line is selected.
             If a timeout has occurred, *result = -2 (used internally).

*/
/*
   Function:   pcbGetReceipt
            pcbGetReceipt returns a 'binary' receipt struct defined in Receipttruct.

   Prototype:   void pcbGetReceipt (ReceiptStruct *rs);

   Input:      *rs   - pointer to result struct holding binary receipt
   Output:      -
   Return:      -

*/
/*
   Function:   pcbEarlyStanPan
            get stan and pan as early as possible in transaction flow.
            This function is used with the flxGetDCProperties method.

   Prototype:   void pcbEarlyStanPan(STAN* stan, PAN* pan, char *DTHR);

   Input:      *stan - pointer to hold stan
            *pan - pointer to hold pan
            *DTHR - pointer to hold transaction timestamp in dthr format
   Output:      stan - stan
            pan - pan
   Return:      -
*/
/*
   Function:   pcbBreakIP
            break the ip idle wait

   Prototype:   int pcbEarlyStanPan(void);

   Input:      -
   Output:      -
   Return:      true if break
*/



/* FLEX FUNCTIONS   */

/*
   Function:   flxInitCallback
            initialize and activate callback function
   Input:      method_id   - id from FLX_CALLBACK enum
            method_ptr   - pointer to callback function
   Output:      -
   Return:      see return value defines

*/
DllExport void flxInitCallback (
         FLX_CALLBACK method_id,
         void* method_ptr);


/*
   Function:   flxConnect
            connect to terminal
            flxdrv.ini file used by function to determine connect type.
   Input:      dummy - internal use , set to 0
   Output:      -
   Return:      see return value defines for flxConnect

*/
DllExport int flxConnect(
         int dummy);

/*
   Function:   flxDisconnect
            disconnect to terminal
            flxdrv.ini file used by function to determine disconnect type.
   Input:      -
   Output:      -
   Return:      SUCCESS

*/
DllExport int flxDisconnect(
         void);

/*
   Function:   flxOpen
            open session to terminal
            flxdrv.ini file used by function to determine open type.
   Input:      -
   Output:      -
   Return:      see return value defines

*/
DllExport int flxOpen(
         void);

/*
   Function:   flxClose
            close session to terminal
            flxdrv.ini file used by function to determine close type.
   Input:      -
   Output:      -
   Return:      SUCCESS

*/
DllExport int flxClose(
         void);


/*
   Function:   flxCardTransaction
            initiate a card transaction
   Input:      transactionType      - from enum FLX_TRANSTYPE
            amount            - transaction amount in smallest currency unit (eg. øre)
            currencyCode      - currency code from CURR_CODES
            merchantInitiative   - 0x00 - PIN transaction
                            0x60 - Offline transaction
                            0x81 - Forced PIN transaction
                            0x82 - Forced Signature transaction
                            see PBS OTRS 2.1 (table 9.3.37) documentation for more information
            refno            - your transaction reference number
                            (returned in ReceiptStruct)
   Output:      *error            - ptr to error code
                            0x00 (SUCCESS)
                            ERR_UNKNOWN
                            ERR_NO_CONNECTION
                            ERR_NO_RECEIPT
   Return:      see return value defines

*/
DllExport int flxCardTransaction(
         FLX_TRANSTYPE transactionType,
         FLX_AMOUNT amount,
         int currencyCode,
         unsigned char merchantInitiative,
         const unsigned int refno,
         unsigned int *error);

/*
   Function:   flxCompleteExtCardTransaction
            used to complete a extern (local) card transaction
   Input:      result      - 0x00 approves the transaction
                      0x01 rejects the transaction
   Output:      -
   Return:      see return value defines

*/
DllExport int flxCompleteExtCardTransaction(
         int result);

/*
   Function:   flxAdministration
            used to initiate administrative functions in the terminal
   Input:      func      -   function from FLX_ADMIN_FUNCTION enum

   Output:      *error      -   ptr to error code
                        0x00 (SUCCESS)
                        ERR_UNKNOWN
                        ERR_NO_CONNECTION
                        ERR_NO_RECEIPT
   Return:      see return value defines


*/
DllExport int flxAdministration(
         FLX_ADMIN_FUNCTION func,
         unsigned int *error);

/*
   Function:   flxGetDllVersion
            gets dll windows product version
   Input:      -
   Output:      -
   Return:      0x0000   - no version
            0xMMmm   - MM Major Version truncated to 2x16 bit
                   mm Minor version truncated to 2x16 bit
*/
DllExport int flxGetDllVersion(void);

/*
   Function:   flxGetTerminalState
            gets the state of the terminal
   Input:      -
   Output:      -
   Return:      terminal state, consult flxdrv.dll manual
*/
DllExport int flxGetTerminalState(
         void);

/*
   Function:   flxGetFiles
            gets files from the terminal
   Input:      consult flxdrv.dll manual
   Output:      -
   Return:      consult flxdrv.dll manual
*/
DllExport int flxGetFiles(
         const char* dir);

/*
   Function:   flxSetConfiguration
            sets the driver configuration parameter
   Input:      func   -   selects parameter
   Output:      -
   Return:      consult flxdrv.dll manual
*/
DllExport int flxSetConfiguration(
         int func, ...);

/*
   Function:   flxSetTrace
            set dll trace level
   Input:      traceLevel - see trace level defines
   Output:      -
   Return:      -
*/
DllExport void flxSetTrace(
         int traceLevel);

/*
   Function:   flxGetTrace
            return dll trace level
   Input:      -
   Output:      -
   Return:      tracelevel - see trace level defines
*/
DllExport int flxGetTrace(void);

/*
   Function:   int flxGetDCProperties(char stanPan, STAN_PAN *stanPan)
            search the PSAM (version >= 50) for status of previous transactions.
   Input:      stanPan - if 0x80 use stan as search key
                  - if 0x81 use pan as search key
   Output:      dcRes - search result as DC_RESULT struct if return SUCCESS
                   memset to 0 if return is FAILURE

   Return:      FAILURE - if the PSAM cannot be accessed at this time or no search match
            SUCCESS - OK.

*/
DllExport int flxGetDCProperties(char stanPan, STAN_PAN *pStanPan, DC_RESULT *dcRes);

DllExport int flxIdleIProuting(int *error);


#ifdef __cplusplus
}
#endif

#endif // __FLEX_H

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Stig Johansen (21-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 21-12-07 04:45

Michael Vilhelmsen wrote:

Det var en længere 'smøre', det tager nok lidt længere tid.
men:
> Jeg har fundet en flex.h fil.
> Syntes du på et punkt efterlyste en sådan:

Yeps, og i forhold til 'vores snak' om leverandørens 'kvalitet' bemærker
jeg, at din offline funktion ikke er med i den. Vi behøver den principielt
ikke, men det er god latin, at man medleverer en opdateret .h fil sammen
med den opdaterede dll.

Hvor har du værdien af FLX_CALLBACK_STOPLIST fra?

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (21-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 21-12-07 08:58

Stig Johansen formulated the question :
> Michael Vilhelmsen wrote:
>
> Det var en længere 'smøre', det tager nok lidt længere tid.
> men:
>> Jeg har fundet en flex.h fil.
>> Syntes du på et punkt efterlyste en sådan:
>
> Yeps, og i forhold til 'vores snak' om leverandørens 'kvalitet' bemærker
> jeg, at din offline funktion ikke er med i den. Vi behøver den principielt
> ikke, men det er god latin, at man medleverer en opdateret .h fil sammen
> med den opdaterede dll.
>
> Hvor har du værdien af FLX_CALLBACK_STOPLIST fra?

Jeg kan da ikke huske, hvor jeg har ovenstående værdi fra.
Syntes at huske, at jeg vist ringede eller mailede til dem...


Under alle omstændigheder har jeg fået en nyere flex.h fil tilsendt.
Personligt syntes jeg ikke den fortæller mere end de tidligere dokumenter - Men vurder selv.


/***********************************************************
*
* Program: flex.h
* Created:
* Author:
* Copyright: Point Transactions Systems A/S
*
************************************************************
*
* History:
*
* $Log: flex.h,v $
* Revision 1.35 2006/04/06 06:23:47 jfh
* Version 2.2.00
*
* Revision 1.34 2006/03/27 08:11:50 jfh
* Changes to advicelogVB interface from string to length, advicelog()
*
* Revision 1.33 2006/03/20 13:44:05 lnr
* OCX/DLL handling of PreResult and EcrExtendedFunctions
* SetConfiguration( 12 - Selects PreResult
* SetTrace with trace level >= 3 sets SEQNO, FROM state and EVENT extra
*
* Revision 1.32 2006/03/16 12:55:29 jfh
* Change a , to ; in binary tag string for VB
*
* Revision 1.31 2006/03/14 12:01:34 jfh
* Added binary receipt from tags
* Idle ip now disconnect if connected on new connection
*
* Revision 1.30 2006/02/09 13:05:06 jfh
* Added support for ip forwarding to ecr
*
* Revision 1.29 2006/01/27 13:02:32 jfh
* External card doc.
*
* Revision 1.28 2006/01/24 11:10:42 jfh
* pSleep for linux
*
* Revision 1.27 2006/01/23 10:15:52 jfh
* Added configuration of filepath for ini and trace files
*
* Revision 1.26 2006/01/19 07:27:05 jfh
* Added open_no_receipt result
*
* Revision 1.25 2005/12/23 10:20:15 jfh
* flxGetID added
* Backlight on/off
*
* Revision 1.24 2005/12/12 10:41:29 jfh
* Version 2.2.00
* StopList
* Token transactions
* Gratuity
*
* Revision 1.23 2005/11/11 13:06:15 jfh
* Token based payment implemented opu/ecr
*
* Revision 1.22 2005/10/14 08:27:54 jfh
* Prelim implementation of flxSetDCproperties
*
* Revision 1.21 2005/09/19 07:49:33 jfh
* Added timer callback
* New no trace at all
*
* Revision 1.20 2005/08/26 12:26:08 jfh
* Added new flx -getFile, -putFile, -deleteFile
*
* Revision 1.19 2005/07/26 07:04:35 jfh
* Added support for Visual Basic 6
*
* Revision 1.18 2005/07/13 10:56:32 jfh
* Flex functions now callable from Visual Basic 6
*
* Revision 1.17 2005/05/20 09:39:20 jfh
* Changes for building Linux shared Flexdriver lib
*
* Revision 1.16 2005/04/15 08:15:41 jfh
* Removed license functions
* Added prelim ip routing
*
* Revision 1.15 2005/03/29 12:01:48 jfh
* Change include file hirachy
*
* Revision 1.14 2005/02/16 09:13:56 jfh
* Added DC properties previous transaction status
*
* Revision 1.13 2005/02/04 10:13:28 jfh
* Release MUNK
*
* Revision 1.12 2005/02/02 14:56:25 jfh
* New TAGS for binary receipt and dcProperties
*
* Revision 1.11 2005/01/13 12:23:12 jfh
* Added more comments
*
* Revision 1.10 2004/12/07 12:16:10 jfh
* Added internal error
*
* Revision 1.9 2004/11/12 09:47:42 jfh
* Minor changes to layout etc.
*
* Revision 1.8 2004/11/05 14:11:00 jfh
* added trace
*
* Revision 1.7 2004/11/04 12:10:09 jfh
* More documentation added + new prototypes
*
* Revision 1.6 2004/10/25 08:24:15 jfh
* Added crcresult and refnumber
* changed definition of fee and amount to
* FLX_CALLBACK_SET_AMOUNT,   // send amount to terminal from ecr
* FLX_CALLBACK_SET_AMOUNT_FEE,   // send fee to terminal from ecr
* FLX_CALLBACK_GET_AMOUNT_FEE,   // receive fee from terminal to ecr
*
* Revision 1.5 2004/10/05 12:45:04 jfh
* Added binary receipt struct
*
* Revision 1.4 2004/09/10 09:16:33 jlp
* Gebyr på kasse + OPU
* Filtransport til kasse
* Advice to Log
*
* Revision 1.3 2004/07/16 12:12:59 cmo
* TCP/IP communication added.
* flxSetConfiguration rewritten
*
* Revision 1.2 2004/06/29 14:46:09 tmo
* Added "new" header with CVS log
*
*
************************************************************/

/******************************************************************************
Copyright 2004-06 POINT A/S All rights reserved.

File Name: flex.h
Contents: Include file

******************************************************************************/

#ifndef __FLEX_H
#define __FLEX_H


#ifdef __cplusplus
extern "C" { // only need to export C interface if
#endif // used by C++ source code

#ifdef _WIN32
#define DllExport __declspec(dllexport)
#else
#define DllExport
#endif

#define MAX_RECEIPT_SIZE         1600

#ifndef TRUE
#define TRUE 1
#define true TRUE
#endif
#ifndef FALSE
#define FALSE 0
#define false FALSE
#endif

// Generel return values
#define SUCCESS                  0x00
#define FAILURE                  0x01
#define FILE_ERROR               0x02

//flxOpen return value
#define OPEN_NO_RECEIPT            0x13

// flxConnect return values
#define CONNECT_OK               0x00
#define CONNECT_NO_INIFILE         0x01
#define CONNECT_INIFILE_READ_ERROR   0x02
#define CONNECT_COMPORTINITFAILURE   0x03
#define CONNECT_SW_NOTCOMPATIBLE   0x04
#define CONNECT_TERM_NOT_RESP      0x05
#define CONNECT_COMPORTOPEN         0x06

// Generel flx error values
#define DATALINKERROR            0x07
#define FUNCTION_NOT_POSSIBLE      0x08
#define TIMEOUT_IN_COMMUNICATION   0x09
#define CONNECT_NO_LICENCE 0x0A
#define CONNECT_INTERNAL_ERROR 0x0B

// flxCardTransaction return values when local card
#define LOCALCARD_OK 0x10
#define LOCALCARD_NOT_OK 0x11

// Trace level defines, tracefile placed in cwd
enum {
   CONF_PARAM = 1,      // Placement of inifile
   CONF_TRACE,         // Enable trace
   CONF_EXTTRACE,      // Enable extensive tracing
   CONF_EXTTRACE_PLUS,   // Enable extensive tracing with append
   CONF_FILEPATH,      // Define directory path for flxdrv.ini and trace files
   CONF_NO_TRACE_AT_ALL=16
};

// Terminal/ECR communication communication type
enum {
   RS232_COMM = 1,
   ETHERNET_COMM
};

// CALLBACK METHODS
typedef enum {
   FLX_CALLBACK_SET_CARDDATA = 0,
   FLX_CALLBACK_PRINT_RECEIPT,
   FLX_CALLBACK_DISPLAY_STATUS,
   FLX_CALLBACK_ABORT,
   FLX_CALLBACK_EXTCARDCONFIRM,
   FLX_CALLBACK_VERSIGCONFIRM,            // 5
   FLX_CALLBACK_ADVICEFLAG,
   FLX_CALLBACK_SET_AMOUNT,            // send amount to terminal from ecr
   FLX_CALLBACK_SET_AMOUNT_FEE,         // send fee to terminal from ecr
   FLX_CALLBACK_GET_AMOUNT_FEE,         // receive fee from terminal to ecr
   FLX_CALLBACK_STATUSTRACE,            // 10
   FLX_CALLBACK_STATETRACE,
   FLX_CALLBACK_ADVICELOG,
   FLX_CALLBACK_MENU,
   FLX_CALLBACK_MENURESULT,
   FLX_CALLBACK_GET_BINARY_RECEIPT,      // 15
   FLX_CALLBACK_EARLY_STAN_PAN,
   FLX_CALLBACK_BREAK_IP,
   FLX_CALLBACK_TIMER,
   FLX_CALLBACK_PUT_TOKEN,
   FLX_CALLBACK_GET_TOKEN,               // 20
   FLX_CALLBACK_SET_AMOUNT_GRATUITY,      // send gratuity to terminal from ecr
   FLX_CALLBACK_STOPLIST,
   FLX_CALLBACK_PRE_RESULT,            // New by lnr 060112
   FLX_CALLBACK_SET_ECR_EXTENDED_FUNCTIONS,   // New by lnr 060113
} FLX_CALLBACK;

// Abort callback return values
#define OPERATORWISHTOABORT         0x01
#define OPERATORDONOTWISHTOABORT   0x02

// Receipt callback return values
#define RECEIPT_OK               0x01
#define RECEIPT_NOTOK            0x00

// verSigConfirmation
// used in resultMenu (and stopList)
#define SIGNATURE_OK            0x01
#define SIGNATURE_NOTOK            0x00
#define SIGNATURE_NOTKNOWNYET      0x02

// resultMenu
#define MENU_RESULT               0x03

// Carddata callback return values
#define CARDNUMBER_OK            0x01   // Card OK, (external card OK do not confirm amount)
#define CARDNUMBER_OK_CONFIRM 0x03   // External card OK and confirm amount.
#define CARDNUMBER_NOTOK         0x00

// cardType values
#define PBS_CARD               0x00
#define OTHER_CARD               0x01


// TRANSACTION METHODS
typedef enum {
   FLX_TRANS_PURCHASE = 0,               // Debit transaction
   FLX_TRANS_REFUND,                  // Credit transaction
FLX_TRANS_ORIGINAL_AUTH,            // Original Authorization, outputs a token
FLX_TRANS_SUPP_AUTH,               // Token based transaction (Not implemented by PBS Host nov. 2005)
FLX_TRANS_CAPTURE,                  // Token based transaction
FLX_TRANS_REVERSAL_AUTH,            // Token based transaction
} FLX_TRANSTYPE;

// ERROR CODES
enum {
   ERR_UNKNOWN = 0x00010000,
   ERR_TERM_NOT_READY,
   ERR_NO_CONNECTION,
   ERR_NO_RECEIPT,
   ERR_SW_NOTCOMPATIBLE,
   ERR_NO_LICENCE,
   ERR_TOKEN_TRANS,
};

// ADMINISTRATION FUNCTIONS
typedef enum{
ADMIN_ENDOFDAY = 1,
ADMIN_ENDOFDAYLOG,
ADMIN_REPORT_TERMINALREPORT,
ADMIN_REPORT_TOTALS,
ADMIN_REPORT_LOG,            // 5
ADMIN_REPORT_OLDLOG,
ADMIN_LASTRECEIPT,
ADMIN_UNLOCK_RECEIPT,
ADMIN_CLOCKSYNCPBS,
ADMIN_CLOCKSYNCPOINT,         //10
ADMIN_SENDLOG,
ADMIN_CLEARDATASTORE,
ADMIN_DOWNLOADPROGRAM,
ADMIN_DOWNLOADPARAM,
ADMIN_DOWNLOADPAN,            //15
ADMIN_DOWNLOADTLCMDB,
ADMIN_RESTORETLCMDB,
ADMIN_CONTRASTUP,
ADMIN_CONTRASTDOWN,
ADMIN_RESTARTTERMINAL,         //20
ADMIN_EJECTCARD,
ADMIN_MSC,               // For future use (fetch the card range table)
ADMIN_BACKLIGHT_ON,
ADMIN_BACKLIGHT_OFF,
ADMIN_MAX,               // last entry
} FLX_ADMIN_FUNCTION;

// ADDITIONAL COMMANDS (not for use in flxAdministration)
#define ADMIN_GET_DC_PROPERTIES_STAN   0x80
#define ADMIN_GET_DC_PROPERTIES_PAN      0x81
#define ADMIN_GET_ID               0x83
#define ADMIN_SET_ECR_EXTENDED_FUNCTIONS   0x84
#define ADMIN_GET_ECR_EXTENDED_FUNCTIONS   0x85


// CURRENCY CODES
typedef enum {
   DKK = 208,      // DK Kroner
   ISK = 352,      // IS Kroner
   JPY = 392,      // JP Yen
   NOK = 578,      // N Kroner
   SEK = 752,      // S Kroner
   CHF = 756,      // SW Francs
   GBP = 826,      // GB Pound
   USD = 840,      // US Dollar
   EUR = 978,      // Euro
} CURR_CODES;

// Merchant Initiative
typedef enum {
   MI_PIN = 0,
   MI_OFFLINE = 0x60,
   MI_FORCED_PIN = 0x81,
   MI_FORCED_SIGNATURE = 0x82,
} FLX_MI;

#ifndef WIN32
typedef unsigned long FLX_AMOUNT;   // Amount must be 4 bytes.
#else
typedef unsigned int FLX_AMOUNT;   // Use 32 bit Windows
#endif


/* BINARY RECEIPT INFO STRUCT RETURNED BY FLX_CALLBACK_GET_BINARY_RECEIPT */

#ifndef _TIME_T_DEFINED
#ifndef BUILDING_LINUX_DLL
typedef long time_t; /* time value */
#endif
#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
#endif

/*
   The ReceiptStruct is data extracted from the receipt generated by the terminal.
   The Terminal must be configured to send the information to the dll.
   The struct is reset to all zeros by default, and only valid receipt information
   is mapped into the struct. Consult Point for more information.
*/

typedef struct {
   time_t      gmtime;               // Unix time stamp (gmt)
FLX_AMOUNT   total;               // total amount in smallest currency unit
   FLX_AMOUNT   extra;               // extra -
   FLX_AMOUNT   fee;               // fee -
   FLX_AMOUNT   gratuity;            // gratuity -
int       currency;            // Currency code (208=DKK, 978=EUR, 840=USD etc.)
   int       Stan;               // PBS reference number converted from BCD code
int       PSAM_Creator;         // PSAM #
   int       PSAM_ID;            // PSAM ID #
   int       MTI;               // PBS apacs transaction code
   int       Asw1Asw2;            // PSAM retur code (see OTRS specification)
   int       ActionCode;            // Transaction result code
   int         refNr;               // Transaction reference number passed from user

   char      pbsResult;            // PBS Transaction result
   char    CvmStatus;            // Cardholder verification method (eg. if signature required) see EMV specs.
   char    CardDataSource;         // Magnetic- or chip card
   char    TR;                  // Transaction request
   char    nota;               // True if signature on receipt
   char    copy;               // True if receipt copy
char    mt;                  // EMV decline code see EMV specification
   char    psn;               // EMV pan sequence number see EMV specification
   char    lenPAN;               // Length of PAN
char    lenAID;               // Length of AID

   char    PAN[10];            // Primary account number BCD code
   char      AID[16];            // EMV application ident.
   char    ATC[2];               // EMV value see EMV specification
   char    AED[3];               // EMV value see EMV specification
   char    ARC[2];               // EMV value see EMV specification
char    PosEntryMode[3];      // Transaktionen information see OTRS and EMV specification.

int         number;               // Merchant PBS number
   char    authorizationCode[6+1];   // PBS authorization code as string
   char    CardName[16+1];         // Card name as string (+1 indicate string termination '\0')
   char    TermIdent[8+1];         // Terminal ID string
char    name[18+1];            // Merchant name as string
char    city[16+1];            // Merchant city as string
char    address[24+1];         // Merchant address as string
char    zip_code[8+1];         // Merchant zip code as string
char    phone[24+1];         // Merchant phone number as string
char    cvr[12+1];            // Merchant CVR number as string

} ReceiptStruct;


/* Structs used by the flxGetDCproperties callback method   */

typedef struct {
unsigned char len;
unsigned char data[10];
} PAN;

typedef struct {
   unsigned char data[3];
} STAN;

typedef union {
   STAN   stan;
   PAN   pan;
} STAN_PAN;

typedef struct {
   STAN      refStan;         // unique psam transaction identifier
   FLX_AMOUNT   amount;
   int         currc;            // curreccy code
   int         curre;            // currency exponent
   char      DTHR[5];         // PBS timestamp year, month, day, hour, minute
} DC_RESULT;

// Additional Transaction Information (used in SEP/OPEL)
typedef struct {
   char   len;
   char   data[15];
} DC_ATI;

/* TOKEN definitions               */
#define MAX_TOKEN_LENGTH 1200
#define TOKEN_EMV 0xd2
#define TOKEN_MSC 0xd4
#define TOKEN_KEY 0xd6


/*
   These CALLBACK FUNCTIONS are defined and coded in the ECR software
   They are documented here for your convinience
   These functions must be implemented by the ECR when mandatory or when used
   (e.i. activated and defined using flxInitCallback).
*/
/*
   Function:   pcbPrintReceipt
            printReceipt prints a formatted receipt or report.

   Prototype:   int printReceipt(unsigned int receipt_status, const char* cText);

   Input:      receipt_status   - 0x02 receipt requires verification
                         0x01 if there are missing segments (e.g. during ADMIN_REPORT_LOG)
                         0x00 if it is the last/whole segment (all transaction receipts).
                         (Clarification: use bit 0 (LSB) to cut between receipts)

            cText         - receipt text coded as ISO 8859-15 and 0 terminated.
                         maximum length in 1000 characters incl. '\0'.
                         If a larger text must be printed divided in smaller segments.

   Output:                  -
   Return:      RECEIPT_OK      - receipt printed OK
            RECEIPT_NOTOK   - receipt NOT printed OK


*/
/*
   Function:   pcbAbort
            printAbort asks if operator whish to abort currect transaction.
            During transactions the flex-driver repeatedly calls the abortTransaction function.
            Notice that even though the ECR tries to abort a Transaction, it might not be aborted.
            It is the Terminal that decides if the Transaction is aborted, or not.
            This function must be implement

   Prototype:   int pcbAbort (void);

   Input:      -

   Output:      -               -
   Return:      OPERATORWISHTOABORT         - Abort
            OPERATORDONOTWISHTOABORT   - do not abort


*/
/*
   Function:   pcbSetCarddata
            pcbSetCarddata gives cardnumber cardtype and crc (card reconcilliation counter id).
            Can be used by the ECR to reject certain types of credit cards,
            e.g. if a customer wishes to get some cash together with the purchased item,
            then the ECR should ensure that the swiped card isn't a credit card.

   Prototype:   int setCarddata(const char *cPan, int cardtype);

   Input:      *cPan      - pointer to 8 first numbers in cardnumber(pan),crc in ascii
                      (e.g. 54130347,1 (1 is dankort))
            cardtype   - PBS_CARD      (card handled by PBS)
                      OTHER_CARD   (local card handled by ECR)

   Output:      -
   Return:      CARDNUMBER_OK         - cardnumber ok
            CARDNUMBER_OK_CONFIRM   - cardnumber (e.g. local card) OK
            CARDNUMBER_NOTOK      - cardnumber not ok


*/
/*
   Function:   pcbDisplayStatus
            pcbDisplayStatus gives an ascii status line

   Prototype:   void pcbDisplayStatus(const char cStat[21], unsigned int line);

   Input:      cStat[]      - pointer 20 char ascii string plus '\0' termination coded as ISO 8859-15
            line      - suggested status line number (1-4)

   Output:      -
   Return:      -

*/
/*
   Function:   pcbVerSigConfirm
            pcbVerSigConfirm asks for signature approval on a signaturetransaction.
            E.g. it could be implemented so the operator e.g. presses 'F1' for approval and 'F2' for rejected.
            The PSAM decides if this functionality is used or not.
            If it is not called and the transaction is approved, both receipts will be sent from the terminal straight away.
            If the signature afterwards seems fake, the operator must run a refund.

   Prototype:   int pcbVerSigConfirm (void);

   Input:      -
   Output:      -
   Return:      SIGNATURE_OK
            SIGNATURE_NOTOK
            SIGNATURE_NOTKNOWNYET

*/
/*
   Function:   pcbAdviceFlag
            pcbAdviceFlag signals that balancing/endofday routine is nessesary
            Meaning that the ECR must not be able to run further transactions before the endofday routine is run and approved.
            This function is mandatory to implement


   Prototype:   void pcbAdviceFlag (void);

   Input:      -
   Output:      -
   Return:      -

*/
/*
   Function:   pcbSetAmount
            pcbSetAmount sets the transaction amount
            If this function isn't initialised in the flxInitCallback function,
            then the amount given in the flxCardTransaction is used.

   Prototype:   FLX_AMOUNT pcbSetAmount(void);

   Input:      -
   Output:      -
   Return:      FLX_AMOUNT - the transaction amount (always positive)
                      amount in lowest currency denomination (e.g. øre).

*/
/*
   Function:   pcbGetAmountFee
            pcbGetAmountFee gives the fee calculated in the terminal.

   Prototype:   void pcbGetAmountFee(FLX_AMOUNT fee);

   Input:      fee   - fee
   Output:      -
   Return:      -

*/
/*
   Function:   pcbSetAmountFee
            pcbSetAmountFee gives the fee calculated in the terminal.

   Prototype:   FLX_AMOUNT pcbSetAmountFee(void);

   Input:      -
   Output:      -
   Return:      FLX_AMOUNT - the transaction fee (always positive) calculated by the ECR
                      amount in lowest currency denomination (e.g. øre).
                      if used in with pcbGetAmountFee, it overrules the terminal fee.

*/
/*
   Function:   pcbSetAmountGratuity
            pcbSetAmountGratuity sets the transaction gratuity amount

   Prototype:   FLX_AMOUNT pcbSetAmountGratuity(void);

   Input:      -
   Output:      -
   Return:      FLX_AMOUNT - the transaction gratuity amount (always positive)
                      amount in lowest currency denomination (e.g. øre).

*/
/*
   Function:   pcbStatusTrace
            pcbStatusTrace

   Prototype:   void pcbStatusTrace (const char *trace);

   Input:      -
   Output:      -
   Return:      -
*/
/*
   Function:   pcbStateTrace
            pcbStateTrace

   Prototype:   void pcbStateTrace (int state);

   Input:      -
   Output:      -
   Return:      -
*/
/*
   Function:   pcbAdviceLog
            pcbAdviceLog sends copies of datastore operations to the ECR.
            The transaction time is increased by approx half a second when using this function.

   Prototype:   void adviceLog (unsigned int len, const unsigned char* data);

   Input:      len      - length of advice data
            *data   - pointer to advise data
   Output:      -
   Return:      -
*/
/*
   Function:   pcbMenu
            pcbMenu is currently used to display information to the operator.
            E.g. if or if not an EMV card is placed correctly in the terminal (command=0).
            The function is also used for the operator to choose between EMV applications
            in correlation with refund transactions (10 <= command >= 1).

   Prototype:   void pcbMenu(unsigned char command, int timeout, unsigned char lines, const char menus[][21]);

   Input:      command      - command (or suggested line to display).
                      0: EMV card inserted correct?
                      1-10: suggested menu to display.
            timeout      - timeout value that the ECR must answer whihin (using pcbMenuResult)
            lines      - number of lines in menu (max. 10)
            menus[][]   - menulines in ascii from 1 to 10
                      each line is 20 char plus terminating '\0'.
   Output:      -
   Return:      -
*/
/*
   Function:   pcbMenuResult
            pcbMenuResult is called repetitively (like abort), to verify the choice made by the operator,
            when a menu is displayed on the ECR screen.

   Prototype:   int pcbMenuResult(char *result);

   Input:      *result   - pointer to result holding selected line in menu
   Output:      - if EMV card inserted correct? use
             *result = -1 (or 0) for no
             *result = 1 for yes
             if APPLICATION SELECT return
             *result = selected menu line (1-10)

   Return:      0 - the answer isn’t known yet (the operator hasn’t pressed a key) and no timeout has occurred.
            1 - the chosen menu point must be entered in the result variable
             e.g. *result = 1 if first menu line is selected.
             If a timeout has occurred, *result = -2 (used internally).

*/
/*
   Function:   pcbGetReceipt
            pcbGetReceipt returns a 'binary' receipt struct defined in Receipttruct.

   Prototype:   void pcbGetReceipt (ReceiptStruct *rs);

   Input:      *rs   - pointer to result struct holding binary receipt
   Output:      -
   Return:      -

*/
/*
   Function:   pcbEarlyStanPan
            get stan and pan as early as possible in transaction flow.
            This function is used with the flxGetDCProperties method.

   Prototype:   void pcbEarlyStanPan(STAN* stan, PAN* pan, char *DTHR);

   Input:      *stan - pointer to hold stan
            *pan - pointer to hold pan
            *DTHR - pointer to hold transaction timestamp in dthr format
   Output:      stan - stan
            pan - pan
   Return:      -
*/
/*
   Function:   pcbBreakIP
            break the ip idle wait

   Prototype:   int pcbBreakIP(void);

   Input:      -
   Output:      -
   Return:      true if break
*/
/*
   Function:   pcbTimer      (not in linux .so version)
            break the ip idle wait

   Prototype:   int pcbTimer(int millisec);

   Input:      millisec - timer value in milli seconds the timer was started with
   Output:      -
   Return:      -
*/
/*
   Function:   pcbPutToken
            Send a transaction token to terminal from ECR

   Prototype:   void pcbPutToken(size_t *TokenLength, unsigned char *TokenData);

   Input:      *TokenLength - Pointer to length of token
            *TokenData    -   Token
   Output:      -
   Return:      -
*/
/*
   Function:   pcbGetToken(size_t TokenLength, const unsigned char *TokenData, const char *TokenId)
            Send a transaction token from terminal to ECR

   Prototype:   void pcbGetToken(size_t TokenLength, unsigned char *TokenData);

   Input:      TokenLength -   length of token
            *Tokendata    -   Token
            *TokenId    - Unique token id
   Output:      -
   Return:      RECEIPT_OK    - Token OK
    RECEIPT_NOTOK - Token not OK (something wrong with this token)
*/
/*
   Function:   pcbStopList
            Ask operator for transaction authorization

   Prototype:   int pcbStopList(const char *Code);

   Input:      Code   - ptr to authorization code (issued by PBS)
   Output:      -
   Return:      0      - the answer isn’t known yet.
            1      - the pcbStopList Code is ready
*/


/* FLEX FUNCTIONS   */

/*
   Function:   flxInitCallback
            initialize and activate callback function
   Input:      method_id   - id from FLX_CALLBACK enum
            method_ptr   - pointer to callback function
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
*/
DllExport void flxInitCallback (
         FLX_CALLBACK method_id,
         void* method_ptr);


/*
   Function:   flxConnect
            connect to terminal
            flxdrv.ini file used by function to determine connect type.
   Input:      dummy - internal use , set to 0
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
*/
DllExport int flxConnect(
         int dummy);

/*
   Function:   flxDisconnect
            disconnect to terminal
            flxdrv.ini file used by function to determine disconnect type.
   Input:      -
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
*/
DllExport int flxDisconnect(
         void);

/*
   Function:   flxOpen
            open session to terminal
            flxdrv.ini file used by function to determine open type.
   Input:      -
   Output:      -
   Return:      OPEN_NO_RECEIPT - if open but terminal in no receipt state
            FAILURE         - not OK
            SUCCESS         - OK.
*/
DllExport int flxOpen(
         void);

/*
   Function:   flxClose
            close session to terminal
            flxdrv.ini file used by function to determine close type.
   Input:      -
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
*/
DllExport int flxClose(
         void);


/*
   Function:   flxCardTransaction
            initiate a card transaction
   Input:      transactionType      - from enum FLX_TRANSTYPE
            amount            - transaction amount in smallest currency unit (eg. øre)
            currencyCode      - currency code from CURR_CODES
            merchantInitiative   - from enum FLX_MI
                            see PBS OTRS 2.1 (table 9.3.37) documentation for more information
            refno            - your transaction reference number
                            (returned in ReceiptStruct)
   Output:      *error            - ptr to error code
                            0x00 (SUCCESS)
                            ERR_UNKNOWN
                            ERR_NO_CONNECTION
                            ERR_NO_RECEIPT
   Return:      FAILURE            - not OK
            SUCCESS            - OK.
            LOCALCARD_NOT_OK   - Local Card transaction not approved (use flxCompleteExtCardTransaction to complete)
            LOCALCARD_OK      - Local Card transaction approved (use flxCompleteExtCardTransaction to complete)
*/
DllExport int flxCardTransaction(
         FLX_TRANSTYPE transactionType,
         FLX_AMOUNT amount,
         int currencyCode,
         unsigned char merchantInitiative,
         const unsigned int refno,
         unsigned int *error);

/*
   Function:   flxCompleteExtCardTransaction
            used to complete a extern (local) card transaction
   Input:      result            - 0x00 approves the transaction
                           - 0x01 rejects the transaction
   Output:      -
   Return:      FAILURE            - PBS transaction not approved
            SUCCESS            - PBS transaction approved
*/
DllExport int flxCompleteExtCardTransaction(
         int result);

/*
   Function:   flxAdministration
            used to initiate administrative functions in the terminal
   Input:      func      -   function from FLX_ADMIN_FUNCTION enum

   Output:      *error      -   ptr to error code
                        0x00 (SUCCESS)
                        ERR_UNKNOWN
                        ERR_NO_CONNECTION
                        ERR_NO_RECEIPT
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
*/
DllExport int flxAdministration(
         FLX_ADMIN_FUNCTION func,
         unsigned int *error);

/*
   Function:   flxGetDllVersion
            gets dll windows product version
   Input:      -
   Output:      -
   Return:      0x0000   - no version
            0xMMmm   - MM Major Version truncated to 2x16 bit
                   mm Minor version truncated to 2x16 bit
*/
DllExport int flxGetDllVersion(
         void);

/*
   Function:   flxGetTerminalState
            gets the state of the terminal
   Input:      -
   Output:      -
   Return:      terminal state, consult flxdrv.dll manual
*/
DllExport int flxGetTerminalState(
         void);

/*
   Function:   flxGetFile
            gets a file from the terminal
   Input:      consult flxdrv.dll manual
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
            FILE_ERROR   - file not present
*/
DllExport int flxGetFile(
         const char *localname,
         const char *remotename,
         int backup);
/*
   Function:   flxGetFiles
            gets files from the terminal
   Input:      consult flxdrv.dll manual
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
            FILE_ERROR   - file not present
*/

DllExport int flxGetFiles(
         const char* dir);

/*
   Function:   flxDeleteFile
            deletes a file (and its backup) from the terminal
   Input:      consult flxdrv.dll manual
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
*/
DllExport int flxDeleteFile(
         const char *name,
         int   backup);

/*
   Function:   int flxPutFile
            Transfere a file to terminal.
   Input:      srcFilename - ptr to src filename
            dstFilename - ptr to destination filenáme
            backup      - backup of file if true
   Return:      FAILURE      - not OK
            SUCCESS      - OK.

*/
DllExport int flxPutFile(
         const char* srcFilename,
         const char* dstFilename,
         int   backup);


/*
   Function:   flxSetConfiguration
            sets the driver configuration parameter
   Input:      func   -   selects parameter
   Output:      -
   Return:      FAILURE      - not OK
            SUCCESS      - OK.
*/
DllExport int flxSetConfiguration(
         int func, ...);

/*
   Function:   flxSetTrace
            set dll trace level
   Input:      traceLevel - see trace level defines
   Output:      -
   Return:      -
*/
DllExport void flxSetTrace(
         int traceLevel);

/*
   Function:   flxGetTrace
            return dll trace level
   Input:      -
   Output:      -
   Return:      tracelevel - see trace level defines
*/
DllExport int flxGetTrace(
         void);

/*
   Function:   int flxGetDCProperties(char stanPan, STAN_PAN *stanPan)
            search the PSAM (version >= 50) for status of previous transactions.
   Input:      stanPan - if 0x80 use stan as search key
                  - if 0x81 use pan as search key
   Output:      dcRes - search result as DC_RESULT struct if return SUCCESS
                   memset to 0 if return is FAILURE

   Return:      != 0 - if the PSAM cannot be accessed at this time or no search match (psam code)
            0    - OK.

*/
DllExport int flxGetDCProperties(
         char stanPan,
         STAN_PAN *pStanPan,
         DC_RESULT *dcRes);


/*
   Function:   int flxSetDCProperties(char stanPan, STAN_PAN *stanPan)
            search the PSAM (version >= 50) for status of previous transactions.
   Input:

   Return:      != 0 - if the PSAM cannot be accessed at this time or no search match (psam code)
            0    - OK.

*/

DllExport int flxSetDCProperties(
         char command,
         DC_ATI *dcati);

/*
   Function:   int flxGetID(void)
            Return unique Point terminal ID.
   Input:

   Return:      != 0 - Unique Point terminal ID (e.g. 990125)
            0    - No ID not found.

*/

DllExport int flxGetID(void);

/*
   Function:   int flxIdleIProuting
            Continue idle 'IP routing' (forwarding of ip to/from serial port).

   Input:      syncronize - if 0 the function continues untill pbcBreakIP returns 1
    if 1 the function looks for a syncframe received from terminal
                      and continues untill pcbBreakIP callback return 1

   Output:      error - error code (e.g. not connected)

   Return:      FAILURE - not OK
            SUCCESS   - OK.

*/
DllExport int flxIdleIPforwarding(
         int syncronize, int *error);

/*
   Function:   int flxGetSetEcrExtendedFunctions(char command, int *resultvalue)

   Input: command
            ADMIN_GET_ECR_EXTENDED_FUNCTIONS = 0x85
            ADMIN_SET_ECR_EXTENDED_FUNCTIONS = 0x84

            resultvalue
            If ADMIN_SET_ECR_EXTENDED_FUNCTIONS
             Pointer to variable containing value to set EcrExtendedFunctions to in terminal
          If ADMIN_GET_ECR_EXTENDED_FUNCTIONS
             Pointer to variable to return value of terminals EcrExtendedFunction


   Return:      != 0 - Unable to SET/GET value of terminals EcrExtendedFunctions
            0    - OK.

*/

DllExport int flxGetSetEcrExtendedFunctions(
         char command,
         int *resultvalue);




#ifdef __cplusplus
}
#endif

#endif // __FLEX_H

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Stig Johansen (22-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 22-12-07 05:27

Michael Vilhelmsen wrote:

> Under alle omstændigheder har jeg fået en nyere flex.h fil tilsendt.
> Personligt syntes jeg ikke den fortæller mere end de tidligere dokumenter
> - Men vurder selv.

Den fortæller umiddelbart nogle ting (undskyld hvis jeg er for hård):

> // CALLBACK METHODS
> typedef enum {
Man er rent ud sagt nogle fjolser, der vælger enum frem for konstatnet.

> FLX_CALLBACK_SET_CARDDATA = 0,
Generelt flagrer man mellem offset værdier (se nogle af de andre)

> FLX_CALLBACK_PRINT_RECEIPT,
> FLX_CALLBACK_DISPLAY_STATUS,
> FLX_CALLBACK_ABORT,
> FLX_CALLBACK_EXTCARDCONFIRM,
> FLX_CALLBACK_VERSIGCONFIRM, // 5
Hov - allerede her mistede man overblikket - det var 5 og ikke 6 ....

> FLX_CALLBACK_ADVICEFLAG,
> FLX_CALLBACK_SET_AMOUNT, // send amount to terminal from ecr
> FLX_CALLBACK_SET_AMOUNT_FEE, // send fee to terminal from ecr
> FLX_CALLBACK_GET_AMOUNT_FEE, // receive fee from terminal to ecr
> FLX_CALLBACK_STATUSTRACE, // 10
> FLX_CALLBACK_STATETRACE,
> FLX_CALLBACK_ADVICELOG,
> FLX_CALLBACK_MENU,
> FLX_CALLBACK_MENURESULT,
> FLX_CALLBACK_GET_BINARY_RECEIPT, // 15
> FLX_CALLBACK_EARLY_STAN_PAN,
> FLX_CALLBACK_BREAK_IP,
Her sluttede den forrigr flex.h

> FLX_CALLBACK_TIMER,
> FLX_CALLBACK_PUT_TOKEN,
> FLX_CALLBACK_GET_TOKEN, // 20
> FLX_CALLBACK_SET_AMOUNT_GRATUITY, // send gratuity to terminal from ecr
> FLX_CALLBACK_STOPLIST,
Her har vi vores værdi - 22 må det blive.

> FLX_CALLBACK_PRE_RESULT, // New by lnr 060112
> FLX_CALLBACK_SET_ECR_EXTENDED_FUNCTIONS, // New by lnr 060113
> } FLX_CALLBACK;
>

[snip]

> /*
> Function: pcbStopList
> Ask operator for transaction authorization
>
> Prototype: int pcbStopList(const char *Code);
Her definerer man en pointer til Code

> Input: Code - ptr to authorization code (issued by PBS)
Her fortæller man at Code er en pointer.
Så den er god nok med vores pointer til pointer

Jeg går og leger lidt med tanken om at skrive nogle ækvivalente
demofunktioner i pascal i stedet for at forklare stolpe op og stolpe ned.
Er det ikke bedre på den måde?

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (02-01-2008)
Kommentar
Fra : Michael Vilhelmsen


Dato : 02-01-08 08:27

Stig Johansen pretended :
> Michael Vilhelmsen wrote:
>
>> Under alle omstændigheder har jeg fået en nyere flex.h fil tilsendt.
>> Personligt syntes jeg ikke den fortæller mere end de tidligere dokumenter
>> - Men vurder selv.
>
> Den fortæller umiddelbart nogle ting (undskyld hvis jeg er for hård):
>
>> // CALLBACK METHODS
>> typedef enum {
> Man er rent ud sagt nogle fjolser, der vælger enum frem for konstatnet.
>
>> FLX_CALLBACK_SET_CARDDATA = 0,
> Generelt flagrer man mellem offset værdier (se nogle af de andre)
>
>> FLX_CALLBACK_PRINT_RECEIPT,
>> FLX_CALLBACK_DISPLAY_STATUS,
>> FLX_CALLBACK_ABORT,
>> FLX_CALLBACK_EXTCARDCONFIRM,
>> FLX_CALLBACK_VERSIGCONFIRM, // 5
> Hov - allerede her mistede man overblikket - det var 5 og ikke 6 ....
>
>> FLX_CALLBACK_ADVICEFLAG,
>> FLX_CALLBACK_SET_AMOUNT, // send amount to terminal from ecr
>> FLX_CALLBACK_SET_AMOUNT_FEE, // send fee to terminal from ecr
>> FLX_CALLBACK_GET_AMOUNT_FEE, // receive fee from terminal to ecr
>> FLX_CALLBACK_STATUSTRACE, // 10
>> FLX_CALLBACK_STATETRACE,
>> FLX_CALLBACK_ADVICELOG,
>> FLX_CALLBACK_MENU,
>> FLX_CALLBACK_MENURESULT,
>> FLX_CALLBACK_GET_BINARY_RECEIPT, // 15
>> FLX_CALLBACK_EARLY_STAN_PAN,
>> FLX_CALLBACK_BREAK_IP,
> Her sluttede den forrigr flex.h
>
>> FLX_CALLBACK_TIMER,
>> FLX_CALLBACK_PUT_TOKEN,
>> FLX_CALLBACK_GET_TOKEN, // 20
>> FLX_CALLBACK_SET_AMOUNT_GRATUITY, // send gratuity to terminal from ecr
>> FLX_CALLBACK_STOPLIST,
> Her har vi vores værdi - 22 må det blive.
>
>> FLX_CALLBACK_PRE_RESULT, // New by lnr 060112
>> FLX_CALLBACK_SET_ECR_EXTENDED_FUNCTIONS, // New by lnr 060113
>> } FLX_CALLBACK;
>>
>
> [snip]
>
>> /*
>> Function: pcbStopList
>> Ask operator for transaction authorization
>>
>> Prototype: int pcbStopList(const char *Code);
> Her definerer man en pointer til Code
>
>> Input: Code - ptr to authorization code (issued by PBS)
> Her fortæller man at Code er en pointer.
> Så den er god nok med vores pointer til pointer
>
> Jeg går og leger lidt med tanken om at skrive nogle ækvivalente
> demofunktioner i pascal i stedet for at forklare stolpe op og stolpe ned.
> Er det ikke bedre på den måde?



Jo - jeg har altid bedst kunne fortå ting, når der kommer sammen med et konkret eksempel.
Så tekst kombineret med demofunktion er jo perfekt - Og så behøves der ikke meget tekst

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Ukendt (03-01-2008)
Kommentar
Fra : Ukendt


Dato : 03-01-08 06:34

Jeg tror jeg starter en ny tråd.
Denne her er blevet lidt 'bred' i mine newsreaders.

--

Med venlig hilsen/Best regards
Stig Johansen




Stig Johansen (05-01-2008)
Kommentar
Fra : Stig Johansen


Dato : 05-01-08 14:30

"Stig Johansen" <stig_johansen_it_at_hotmail.com> wrote:

Nå, jeg kan se min OE ovre på Windows PC er sat lidt anderledes op, men men
det er (også) mig.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (11-12-2007)
Kommentar
Fra : Michael Vilhelmsen


Dato : 11-12-07 09:23

Stig Johansen was thinking very hard :
> Michael Vilhelmsen wrote:
>
>> Det er ganske fint alt det du skriver her - Det virker bare ikke.
>
> Ok, men så har vi forsøgt.

Jeps



>
>> Bruger cdecl og stdcall bryder programmet ned, når jeg forlader rutinen
>> (med en AV). Ud over denne ene rutine, er der i programmet mange andre
>> callback rutiner. De er også alle defineret som safecall.
>>
>>
>> Hvis der ikke er VAR på min parameter - Ja så virker programmet, men
>> resultat kommer ikke frem
>>
>> Denne definition:
>> function OfflineAutoCode (VAR RetAutCode : PWideChar) : Integer; SafeCall;
>>
>>
>> Den virker. Hver eneste gang. Uden AV eller noget.
>>
>> Men kan nu egentlig godt følge dig i alt det du siger.
>> Jeg kan bare ikke få det til at virke på nogen af dine måder.
>> Dem som har sat DLLen tilrådighed - De er ikke overdrevent oplysende.
>> Så det er lidt svært at få informationer ad den vej.
>
> Så er de squ tarvelige. Er der en .h med til DLL'en?
> Hvis erklæringen er klippet over fra dokumentationen kan der være fejl i
> den.

Erklæringen kommer fra en PDF fil.
Her kan jeg godt have dem mistænkt for, ikke at skrive det korrekte ned.



>
> Som Thomas er inde på, er det en pointer, eller for den sags skyld en
> adresse, der forventes jfr c-erklæringen.

Så langt er vi i hvert fald enige.


>
> Dvs. hvis vi eks. har (Hvis det er unicode).
>
> Code : WideString ; (Den faktiske streng)
> pCode : PWideString ; (32 bits adresse til den faktiske streng)
>
> Så vil korrekte parametre være:
> function OfflineAutoCode (VAR Code : WideString..
> function OfflineAutoCode (pCode : PWideString..
>
> Når du så bruger både VAR og pointer, er det en adresse til en adresse til
> data. Det mener jeg ville hedde **Code i C.
>
> Hvis du bruger Code skriver du eks:
> Code := '123456' ;
> Hvis du bruger pCode skriver du:
> pCode^ := '123456' ;
>
> Jeg har ikke selv brugt WideStrings (endnu) men strings er normal 0
> termineret i Delphi.
>
> Med det in mente, så:
> *   FillChar(RetAutCode,SizeOf(RetAutCode),#0);
> Her sætter du _adressen_ til NIL
>
> *   lStr       := lStr + lStr;
> Jeg er ikke med på om det er unicode eller ej. Det her bliver til 12
> almindelige tegn, og ikke unicode.
>
> *   RetAutCode := PWideChar(lSTr);
> Her sætter du _adressen_ til det samme som iStr. Men _indholdet_ er stadig
> 12 almindelige tegn, og ikke unicode.
>
> Jeg ville prøve denne her:
> function OfflineAutoCode (var RetAutCode : WideString) : Integer; cdecl;
> begin  //OfflineAutoCode
>     RetAutCode := '123456';
>     frmMain.lblInfo.Caption := RetAutCode;
>     if (RetAutCode='¥¥¥¥¥¥') then
>       Result     := 0
>     else
>       Result     := 1;
> end;
>
> Den burde virke jfr. c erklæringen. Hvis det ikke er unicode alligevel
> bruger du bare en string i stedet.
>
>> Anyway - Programmet virker. Hver gang, som det er nu.
>> Alle andre kombinationer virker bare ikke. Eller giver en decideret AV.
>
> Heller ikke den du lige har fået?


Nope - Den du lige har givet, giver en AV.
Ikke som de andre - Denne er "Out of memory" ....


Men virker gør det altså ikke.


Michael

PS.
Under alle omstændigheder er jeg da glad for, at du gider bruge så lang tid på det.

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Stig Johansen (12-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 12-12-07 04:19

Michael Vilhelmsen wrote:

> PS.
> Under alle omstændigheder er jeg da glad for, at du gider bruge så lang
> tid på det.

Velbekomme, jeg er også glad for at 'rode lidt op' i de sidste 20+ års
erfaringer med den slags.

Jeg fortsætter efter dit andet svar.

--
Med venlig hilsen
Stig Johansen

Stig Johansen (15-12-2007)
Kommentar
Fra : Stig Johansen


Dato : 15-12-07 17:29

Jeg 'kom til' at tænde min gamle WindowsPC, kiggede lige i D7's help, så
lige en kort opfølgning (Det jeg har skrevet var ud af hovedet).

Michael Vilhelmsen wrote:
> Det er ganske fint alt det du skriver her - Det virker bare ikke.
>
> Bruger cdecl og stdcall bryder programmet ned, når jeg forlader rutinen
> (med en AV).

I følge D7 er den god nok. stdcall er til at _kalde_ c-ting, og cdecl er
normalt til at blive _kaldt_ fra c-ting.
Forskellen på de to er _hvem_ der rydder op i stakken (det har jeg ævlet om
et andet sted).

> Ud over denne ene rutine, er der i programmet mange andre
> callback rutiner. De er også alle defineret som safecall.

Det er det, der er bekymrende. _safe_call står defineret som en 'exception
firewall on windows'. Det kunne lyde som om der er et fundamentalt problem,
der bliver 'fejet ind under gulvtæppet'.

--
Med venlig hilsen
Stig Johansen

Michael Vilhelmsen (05-02-2008)
Kommentar
Fra : Michael Vilhelmsen


Dato : 05-02-08 11:03

Hej Stig.

Du er ikke glemt - Du er bare blevet presset temmelig langt ned på min liste.
Den hjælp du gav før jul har været god - Og løste mange af mine problemer.

Men jeg tør altså pt. ikke give et bud på, hvornår jeg får kigget på din opsummering....

Men ellers indtil nu - Tusind tak for hjælpen.

Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Søg
Reklame
Statistik
Spørgsmål : 177577
Tips : 31968
Nyheder : 719565
Indlæg : 6409071
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste