|
FOROS PROFESIONALES WINDEV, WEBDEV y WINDEV Mobile |
| | | | | |
| 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(" ", +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 |
| |
| |
| | | |
|
| | | | |
| | |
| | |
| |
|
|
|