PC SOFT

FOROS PROFESIONALES
WINDEVWEBDEV y WINDEV Mobile

Inicio → WINDEV 2024 → GPF when calling DLL with Structure
GPF when calling DLL with Structure
Iniciado por guest, 26,feb. 2018 10:49 - 8 respuestas
Publicado el 26,febrero 2018 - 10:49
I am trying to call a 3rd party DLL from WinDev22, but whenever the function returns data I get either a GPF error or "WDTst.exe has stopped working".

I believe the issue related to the structure that I pass in and is loaded with the return data, it's described in the DLL documentation as ;

typedef struct {
unsigned char aucEPoSNumber[2+1];
unsigned char ucResponseCode;
unsigned char aucAmount[8+1];
unsigned char ucReturnREP;
unsigned char ucPaymentMode;
unsigned char aucResponseData; //optional
unsigned char aucCurrency[3+1];
unsigned char aucPrivateData[10+1];
unsigned char aucOption[(26*99)+1]; //optional (RFU)
unsigned char aucNonConcertData[50000]; //optional
}CDC__S_DATA_RECEIVE;

I've read through the WinDev documentation on DLL calls (API(), CallDLL32() and API Description) and I can see that there can be issues with C strings. So I have tried the methods described in CallDLL32, with defining strings and assigning them so my code looks like this;

s_aucEPoSNumber is string on 2 // unsigned char aucEPoSNumber[2+1] s_ucResponseCode is string on 1 // unsigned char ucResponseCode s_aucAmount is string on 8 // unsigned char aucAmount[8+1] s_ucReturnREP is string on 1 // unsigned char ucReturnREP s_ucPaymentMode is string on 1 // unsigned char ucPaymentMode s_aucResponseData is string on 1 // unsigned char aucResponseData s_aucCurrency is string on 3 // unsigned char aucCurrency[3+1] s_aucPrivateData is string on 10 // unsigned char aucPrivateData[10+1] s_aucOption is string on (26*99) // unsigned char aucOption[(26*99)+1] s_aucNonConcertData is string on 50000 //unsigned char aucNonConcertData[50000] strDataToReceive is Structure aucEPoSNumber is int ucResponseCode is int aucAmount is int ucReturnREP is int ucPaymentMode is int aucResponseData is int aucCurrency is int aucPrivateData is int aucOption is int aucNonConcertData is int END dataReturn is StrDataToReceive WITH dataReturn :aucEPoSNumber=&s_aucEPoSNumber :ucResponseCode=&s_ucResponseCode :aucAmount=&s_aucAmount :ucReturnREP=&s_ucReturnREP :ucPaymentMode=&s_ucPaymentMode :aucResponseData=&s_aucResponseData :aucCurrency=&s_aucCurrency :aucPrivateData=&s_aucPrivateData :aucOption=&s_aucOption :aucNonConcertData=&s_aucNonConcertData END iReturn is int = -99 iTimeOut is int = 1*6000 cString is string = DataToSend() ConcertTransaction(cString,&dataReturn,iTimeOut)
I've also tried
iReturn=CallDLL32("ComConcert","ConcertTransaction",cString,&dataReturn,iTimeOut)
I've also tried the string length being with the +1, which indicates null terminated values, so for example the aucEPoSNumber as 3 instead of 2. I've also tried all the strings as simple strings and different CallingCOnvention settings.

I've run out of thing to try or read in WinDev help.

Anyone any suggestion or idea on how I could get this to work?
Publicado el 26,febrero 2018 - 12:07
Hi Gary,

try using the C structure converter in WDAPI. While this tool is far from perfect, it should give you a good idea of the direction to go to

Best regards
Publicado el 26,febrero 2018 - 13:22
Hi Fabrice,

WDAPI was not much help, it turned the structure into ;
// This structure was automatically generated // some types of parameters may change // check the type of the specified parameters! CDC__S_DATA_RECEIVE is Structure aucEPoSNumber is int on 2 octets //unsigned char type not found (integer is the most common type, to be CHECKED) ucResponseCode is int //unsigned char type not found (integer is the most common type, to be CHECKED) aucAmount is int on 8 octets //unsigned char type not found (integer is the most common type, to be CHECKED) ucReturnREP is int //unsigned char type not found (integer is the most common type, to be CHECKED) ucPaymentMode is int //unsigned char type not found (integer is the most common type, to be CHECKED) aucResponseData is int //unsigned char type not found (integer is the most common type, to be CHECKED) aucCurrency is int on 3 octets //unsigned char type not found (integer is the most common type, to be CHECKED) aucPrivateData is int on 10 octets //unsigned char type not found (integer is the most common type, to be CHECKED) aucOption is int //unsigned char type not found (integer is the most common type, to be CHECKED) aucNonConcertData is int on 50000 octets //unsigned char type not found (integer is the most common type, to be CHECKED) END
Which won't even compile as 3, 10 and 50000 are invalid settings.

I'm assuming 'octets' here is interchangeable with 'bytes', as I can't find anything in the help on what the octets keyword is for / does.
Publicado el 26,febrero 2018 - 13:57
Hi Gary,

Your strings need to be declared as ASCII strings for API usage. It won't work with WL strings.
s_aucEPoSNumber is ASCII string on 2

Cheers,

Peter Holemans
Publicado el 26,febrero 2018 - 15:05
Hi Peter,

I have tried that and also tried giving them initial values ;
s_aucEPoSNumber is string ASCIIZ on 3 = " "+Charact(0) s_ucResponseCode is string ASCIIZ on 1 =" " s_aucAmount is string ASCIIZ on 9 = RepeatString(" ",8)+Charact(0) s_ucReturnREP is string ASCIIZ on 1 = " " s_ucPaymentMode is string ASCIIZ on 1 = " " s_aucResponseData is string ASCIIZ on 1 = " " s_aucCurrency is string ASCIIZ on 4 = RepeatString(" ",3)+Charact(0) s_aucPrivateData is string ASCIIZ on 11 = RepeatString(" ",10)+Charact(0) s_aucOption is string ASCIIZ on (26*99) = RepeatString(" ",26*99)+Charact(0) s_aucNonConcertData is string ASCIIZ on 50000 = RepeatString(" ",50000)
But to no avail :(

If I let it timeout or abort on the card reader device the DLL is managing then no GPF so it has to be the data in this structure.
Publicado el 26,febrero 2018 - 16:15
Gary,

you use pointers now in the structure itself, is that the correct way?

Maybe you can try this

strDataToReceive is Structure s_aucEPoSNumber is string on 2 // unsigned char aucEPoSNumber[2+1] s_ucResponseCode is string on 1 // unsigned char ucResponseCode s_aucAmount is string on 8 // unsigned char aucAmount[8+1] s_ucReturnREP is string on 1 // unsigned char ucReturnREP s_ucPaymentMode is string on 1 // unsigned char ucPaymentMode s_aucResponseData is string on 1 // unsigned char aucResponseData s_aucCurrency is string on 3 // unsigned char aucCurrency[3+1] s_aucPrivateData is string on 10 // unsigned char aucPrivateData[10+1] s_aucOption is string on (26*99) // unsigned char aucOption[(26*99)+1] s_aucNonConcertData is string on 50000 //unsigned char aucNonConcertData[50000] END iReturn=CallDLL32("ComConcert","ConcertTransaction",cString,&dataReturn,iTimeOut)
But it can be a pain in the.....
I sometimes switch to C++ or C# (using Visual Studio), creating a .NET lib myself, do the complex stuff there, and return the result as a simple string (comma or tab separated or xml). Then in your WD app you can do a (much simpler) call to a .NET library.
I know, you must have some .NET knowledge in turn :rolleyes:
Publicado el 26,febrero 2018 - 17:41
Two points:
1) Character & String on 1 is not the same thing
You define characters as string ASCIIZ on 1...
You should define these as characters: x is character
The reason is that a C string defined with length 1 contains two characters: A character + NULL, so 2 bytes (or more in unicode). A C character only contains one byte (or more in unicode) as it doesn't need the terminating NULL value.

2) What's your project configuration?
- Unicode or ANSI (Depending on the type you may need to call another API)
- 32 or 64 bit (Depending on that you need to call a different DLL)

The GPF points to a memory issue so I would say your structure is binary not correct. Use characters for characters to start with.

Cheers,

Peter Holemans
Publicado el 26,febrero 2018 - 20:51
Gary

Try out as below:

strDataToReceive is Structure
s_aucEPoSNumber is fixed string on 2 // unsigned char aucEPoSNumber[2+1]
s_ucResponseCode is fixed string on 1 // unsigned char ucResponseCode
s_aucAmount is fixed string on 8 // unsigned char aucAmount[8+1]
s_ucReturnREP is fixed string on 1 // unsigned char ucReturnREP
s_ucPaymentMode is fixed string on 1 // unsigned char ucPaymentMode
s_aucResponseData is fixed string on 1 // unsigned char aucResponseData
s_aucCurrency is fixed string on 3 // unsigned char aucCurrency[3+1]
s_aucPrivateData is fixed string on 10 // unsigned char aucPrivateData[10+1]
s_aucOption is fixed string on (26*99) // unsigned char aucOption[(26*99)+1]
s_aucNonConcertData is fixed string on 50000 //unsigned char aucNonConcertData[50000]
END

dataReturn is strDataToReceive

//allocate dataReturn

dataReturn.s_aucEPoSNumber = RepeatString(" ",2) ...
dataReturn.s_aucNonConcertData = RepeatString(" ",255) //since optional

// looks like windev does wrap up NULL on each string if not
// declare s_aucEPoSNumber is fixed string on 3
// dataReturn.s_aucEPoSNumber = RepeatString(" ",2)+NULL

// or use/declare as buffer if it involve UTF8
HTH

King
Publicado el 27,febrero 2018 - 05:39
Hi

Pls also see below sample that I did in 2006 for wav to mp3 conversion from lame dll.

// 21:32:19 Mon.Feb.26 2018 now declare int
//2006.07.04 instead long int // at that time
LHV11 is structure
dwStructVersion is int
dwStructSize is int
dwSampleRate is int
dwReSampleRate is int // DOWNS AMPLERATE, 0=ENCODER DECIDES
nMode is int // BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
dwBitrate is int // CBR bitrate, VBR min bitrate
dwMaxBitrate is int // CBR i gnored, VBR Max bitrate
nPreset is int // Quality preset, use one of the settings of the LAME_QUALITY_PRESET enum
dwMpegVersion is int // FUTURE USE, MPEG-1 OR MPEG-2
dwPsyModel is int
dwEmphasis is int
bPrivate is int
bCRC is int
bCopyright is int
bOriginal is int
bWriteVBRHeader is int // WRITE XING VBR HEADER (1/FALSE)
bEnableVBR is int
nVBRQuality is int
dwVbrAbr_bps is int // Use ABR in stead of nVBRQuality
nVbrMethod is int
bNoRes is int // Disable Bit resorvoir (1/FALSE)
bStrictIso is int
nQuality is int
btReserved is fixed string on 237
//[255-4*sizeof(DWORD)];
end

format1 is structure
LHV1 is LHV11
end

beConfig1 is structure
dwConfig is int
format is format1
END

beConfig is beConfig1
beConfig:dwConfig = 256
beConfig:format:LHV1:dwStructVersion = 1
beConfig:format:LHV1:dwStructSize = 331//331
beConfig:format:LHV1:dwSampleRate = 44100
beConfig:format:LHV1:dwReSampleRate = 0
beConfig:format:LHV1:nMode= 0 //stereo
beConfig:format:LHV1:dwBitrate = 128
beConfig:format:LHV1:nPreset = 5 //2 LQP_HIGH_QUALITY
beConfig:format:LHV1:dwMpegVersion= 1 //MPEG1
beConfig:format:LHV1:dwPsyModel = 0
beConfig:format:LHV1:dwEmphasis = 0
beConfig:format:LHV1:bOriginal = 1
beConfig:format:LHV1:dwMaxBitrate = 320
beConfig:format:LHV1:bCRC = 1
beConfig:format:LHV1:bNoRes = 1
beConfig:format:LHV1:bWriteVBRHeader = 1
beConfig:format:LHV1:btReserved = repeatstring("*", 237)

trace(beConfig:format:LHV1:btReserved )

HTH

Cheers

King