TD7 problems with using external functions of a DLL in C

Discussion forum about all things Team Developer 7.x
xenox75
Italy
Posts: 4
Joined: 11 Oct 2018, 14:42
Location: Italy

TD7 problems with using external functions of a DLL in C

Post by xenox75 » 11 Oct 2018, 15:08

I have a problem with using the external functions of a DLL in C
The function has two typedef struct, one for INPUT and one as an OUTPUT example:

/* INPUT */
typedef struct
{
char TerminalId[8+1];
char AcquirerId[8+1];
char TransactionType[3+1];
}TInputData

/* OUTPUT */
typedef struct
{
char Value[8+1];
char Esito[11+1];
char Code[2+1];
char KODescription[24+1];
}TOutputData

Su GUPTA T.D. 7.0.4 ho definito le 2 struct così:

structPointer
String: char[8]
String: char[8]
String: char[3]

structPointer
Receive String: char[8]
Receive String: char[11]
Receive String: char[2]
Receive String: char[24]


However:
1> If you pass as a second value (AcquirerId = '12345678') it is not read correctly
2> I'm not sure that for example the value char TerminalId [8 + 1] is represented in GUPTA as String: char [8]
3> moreover, the function remains to think and then crashes.

I think it depends on the definition of variables that he does not like.
how could I solve?

Thank you

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1088
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: TD7 problems with using external functions of a DLL in C

Post by Dave Rabelink » 11 Oct 2018, 19:52

I'm not sure TD is handling CHAR types as expected in UNICODE TD versions.

CHAR is 1 byte.

The string you provide is UNICODE and that means each character is 2 bytes.

So,a definition of

Code: Select all

char AcquirerId[8+1];
Expects 8 bytes plus 1 ending byte (NULL character).

The string '12345678' is 16 bytes plus 2 ending NULL bytes.

Probably you need to convert the string to ANSI first.

Code: Select all

Call SalStrToMultiByte( "12345678", sANSI, ENC_ANSI )
And use the sANSI variable to pass into the external function.

The output data should be converted from ANSI to UNICODE using

Code: Select all

Call SalStrToWideChar( sANSIOutput, sOutput, ENC_ANSI )
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

xenox75
Italy
Posts: 4
Joined: 11 Oct 2018, 14:42
Location: Italy

Re: TD7 problems with using external functions of a DLL in C

Post by xenox75 » 17 Oct 2018, 15:49

For the return structure I almost solved:

/ * OUTPUT * /
typedef struct
{
char Value [8 + 1];
char Outcome [11 + 1];
char Code [2 + 1];
char KODescription [24 + 1];
...
} TOutputData


I defined a structPointer with

Code: Select all

Receive String: char [9]
Receive String: char [12]
Receive String: char [3]
Receive String: char [25]
...
in total there are 25 values ​​to be set ... up to the 6th is OK, then if even the 7th value is read, the application crashes
If I set the remaining all as

Code: Select all

Receive String: char [255]
the first value I see the remaining no ...

So instead of:

Code: Select all

Receive String: char [255]
I wanted to use:

Code: Select all

Receive String: LPSTR
So I set only the first one leaving the others as they were set:

Code: Select all

Receive String: LPSTR
Receive String: char [12]
Receive String: char [3]
Receive String: char [25]
...
In this case he asks me to set the length, so I used:
Call SalSetBufferLength (Value, 18)

I put 18 because it should be (8 + 1) * 2 = 18

accept it, but I do not return the value, what am I wrong?

thanks

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1088
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: TD7 problems with using external functions of a DLL in C

Post by Dave Rabelink » 18 Oct 2018, 06:02

I have to correct myself, the remark about having to use SalStrToMultiByte is wrong.
TD will automatically convert UNICODE string to ANSI when using CHAR.
(when using TD5.1 and higher).

So it would be straightforward. Just pass in the variables. But be sure the strings passing in do not exceed the max size.
The char Value [8 + 1]; indicates that the value must be ending with a NULL character. Having 8 char values and 1 null ending character.

So check the size of the input vars like this:

Code: Select all

SalStrLength( TerminalId ) < 9   ! -> this is valid

Could you attach a test application where you call the external function? This way it is clearer how you implemented it.
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

xenox75
Italy
Posts: 4
Joined: 11 Oct 2018, 14:42
Location: Italy

Re: TD7 problems with using external functions of a DLL in C

Post by xenox75 » 18 Oct 2018, 09:56

For the input data I have no problems, because the biggest is this:

Code: Select all

char Contract [128 + 1]
So in "structPointer" I imposed it as

Code: Select all

String: char [129]
In fact, sending data works, the problem is nrl return that I have this structure:

Code: Select all

typedef struct
{
  char TerminalId [8 + 1];
  char AcquireId [11 + 1];
  char TransactionType [3 + 1];
  char TransactionResult [2 + 1];
  char KODescription [24 + 1];
  char CardType [1 + 1];
  char STAN [6 + 1];
  char POSBalance [16 + 1];
  char BankBalance [16 + 1];
  char PAN [19 + 1];
  char AuthorizationCode [6 + 1];
  char OperationNumber [6 + 1];
  char AmountAuth [8 + 1];
  char PreauthorizationCode [9 + 1];
  char ActionCode [3 + 1];
  char DataTrs [7 + 1];
  char AmountEcho [8 + 1];
  char Ticket [MAX_TICKET_LEN + 1];
  char EsitoLetturaTrk2 [3 + 1];
  char Trk2 [40 + 1];
  char EsitoLetturaTrk1 [3 + 1];
  char Trk1 [254 + 1];
  char StatoPos [1 + 1];
  char InfoRelease [64 + 1];
  char Additional DataTagDaGt [255 + 1];
} TPOSData;
First problem:

Code: Select all

char Additional DataTagDaGt [255 + 1];
this should be declared as:

Code: Select all

String: char [256], but the max is 255 so I put String: char [255]
Second problem:

Code: Select all

char Ticket [MAX_TICKET_LEN + 1];
which shows in the definition:

Code: Select all

"#define MAX_TICKET_LEN 4096"
here can give me problems ...

For the input and output I created 2 "Interface" (ECRData Input, POSData Output) and on "Instance Variables" I put all the variables "String"
Example:

Code: Select all

String: TerminalId! TerminalId [8 + 1];
...

The function is called like this:

Code: Select all

Set nRisultatoPOS = IAE17AX_LastResult (
ECRData.Amount
, ECRData.ECRId
, ECRData.PaymentType
, ECRData.TerminalId
, ECRData.Contract
, ECRData.PreauthorizationCode
, ECRData.STAN
, ECRData.Ticket2Ecr
, ECRData.DatiAgg
, ECRData.TypeReprint
, ECRData.TipoStornoR
, ECRData.PANABI
, ECRData.IdAcquirer
, ECRData.DataStornoR
, ECRData.AuthorizationCode
, ECRData.DllType
, ECRData.DatiAddiviIsoRisposta
, ECRData.DatiAddiviTagRisposta
, ECRData.DatiAddiviNumeroTag
, ECRData.DatiAddiviTag1
, ECRData.DatiAdduntiviTag2
, ECRData.DatiAddiviTag3
, ECRData.DatiAdduntiviTag4
, ECRData.ExtendedPaymentType
, POSData.TerminalId
, POSData.AcquirerId
, POSData.TransactionType
, POSData.TransactionResult
, POSData.KODescription
, POSData.CardType
, POSData.STAN
, POSData.POSBalance
, POSData.BankBalance
, POSData.PAN
, POSData.AuthorizationCode
, POSData.OperationNumber
, POSData.AmountAuth
, POSData.PreauthorizationCode
, POSData.ActionCode
, POSData.DataTrs
, POSData.AmountEcho
, POSData.Ticket
, POSData.ExitReadingTrk2
, POSData.Trk2
, POSData.ExitReadingTrk1
, POSData.Trk1
, POSData.StatoPos
, POSData.InfoRelease
, POSData.Additional DataTagDaGt)
With all char gives me problems after the 6th.

So I set the first return value "POSData.TerminalId":

Code: Select all

Receive String: LPSTR
or

Code: Select all

Receive String: LPWSTR
instead of

Code: Select all

Receive String: char [9]
and before invoking the function I put:

Code: Select all

Call SalSetBufferLength (POSData.TerminalId, 18)! 9 * 2 = 18
then I also tried with:

Code: Select all

Call SalSetBufferLength (POSData.TerminalId, 9)
in both cases on POSData.TerminalId I do not return anything.

instead if I put back:

Code: Select all

Receive String: char [9]
Then the value returns to me, but then after the 6th I have no other values ​​..

thanks

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1088
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: TD7 problems with using external functions of a DLL in C

Post by Dave Rabelink » 18 Oct 2018, 11:34

Ah...

Well, in this case I would not use the external struct definitions in TD for the output part.
(you say the input is ok, so keep it that way).

You can define the external function this way:

Code: Select all

Function: IAE17AX_LastResult
	Description:
	Export Ordinal: 0
	Returns
	Parameters
		structPointer
			String: char[9]
			String: char[9]
			....here all input members
		Receive String: LPVOID
Define the output as one single LPVOID.
(do not use LPSTR as this will not work because of the NULL characters for each member).

Use cstructl.apl features to get the values from the output buffer.

Example like this:

Code: Select all

! Set buffer length to the total size of the complete output struct
Call SalSetBufferLength( sOutput, nTotalStructSize )    ! in bytes
!
Call IAE17AX_LastResult( YOUR INPUT VAR1, YOUR INPUT VAR2, ...  , sOutput )
!
Call CStructGetString( sOutput, 0, 9, sTerminalId )		! starts on pos 0, length 9
Call CStructGetString( sOutput, 9, 12, sAcquireId )		! starts on pos 9, length 12
Call CStructGetString( sOutput, 21, 4, sTransactionType )	! starts on pos 21, length 4;
! 
! etc etc. For each member use the correct startpos and length
The cstructl functions do not have the 255 byte limit and you can get the 4096 bytes for member Ticket using CStructGetString.
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

xenox75
Italy
Posts: 4
Joined: 11 Oct 2018, 14:42
Location: Italy

Re: TD7 problems with using external functions of a DLL in C

Post by xenox75 » 18 Oct 2018, 14:04

Dave Rabelink
I did as you said and now it works ...
I only have the problem in the field:
char Ticket [MAX_TICKET_LEN + 1];

Because maybe MAX_TICKET_LEN is a variable value, but I'll do some tests.

For now the data seem to go out and no longer crashes.

Thank you very much, you have been very kind. ;)

Dave Rabelink
Founder/Site Admin
Founder/Site Admin
Netherlands
Posts: 1088
Joined: 24 Feb 2017, 09:12
Location: Gouda, The Netherlands

Re: TD7 problems with using external functions of a DLL in C

Post by Dave Rabelink » 18 Oct 2018, 19:23

xenox75 wrote:
18 Oct 2018, 14:04
I only have the problem in the field:
char Ticket [MAX_TICKET_LEN + 1];
Don't worry, the directive does not change so you can expect it to be 4096.
Regards,
Dave Rabelink

Image
Articles and information on Team Developer Tips & Tricks Wiki
Download samples, documents and resources from TD Sample Vault
Videos on TDWiki YouTube Channel

Return to “General Discussion”

Who is online

Users browsing this forum: [Ccbot] and 0 guests