That Marc
That Marc

Reputation: 1224

Translating DLL Call functions from C to Delphi

So, as the title says, I'm in a struggle with translating a few functions for calling DLL, which I have documentation about in C, but I need to use it in Delphi.

After few initial tries, and after solving some compiler errors after translation, with the help of you guys (topic here), some of them still doesn't work. Mostly it's the problem with variables as parameters...

First the subject: I bought an USB logic analyzer and oscilloscope, made by some Czech company, which comes with rather basic and limited software, but has a DLL and (poor) documentation on how to implement it in our own applications in order to communicate with the analyzer.

Now, this documentation (found here) has several functions, written in C (code paragraph 1 below). I've translated them all to Delphi (code paragraph 2 below), but only got around half of them working.

I'd need some help to determine where the issue stands:

Note: All of the functions and all data communication work correctly using original software! Therefore, I believe it's safe to assume that everything that isn't working is the issue in either DLL or my Delphi code, not of the device itself...


int SetAnalogChannels(int CH1Gain, int CH2Gain, bool CH1Couple, bool
CH2Couple, bool CH1Multiplier, bool CH2Multiplier)

CHXGain: Possible values are 10, 20, 50, 100, 200, 500 mV/div. Send just the integer to set this value

Here, I have trouble sending the int CH1Gain and int CH2Gain. Device always returns 0 to the function, which means that Gain parameters are invalid. Don't have a clue of why...

function SetAnalogChannels(CH1Gain, CH2Gain: integer; CH1Couple, CH2Couple,
                           CH1Multiplier, CH2Multiplier: boolean): integer;
                           stdcall; external 'E_l80.dll';

long RetrieveDSOData(unsigned char whatchannels, double *DSOCH1,
double *DSOCH2, unsigned short *LADATA, unsigned char Nth_Sample)

DSOCHX: A pointer to an array of voltage points from the DSO channels.
LADATA: A pointer to an array of LA data.

Here, I have no idea what that types should be, if they really are pointers to the array (although there's no [] marks. But from logical view of the device, it should be an array. With max 32 values...).
Edit: I just figured out my mistake and shallow reading of the docs. The return of the function gives the exact size of the arrays!

function RetrieveDSOData(whatchannels: uchar; var DSOCH1, DSOCH2: TLAArray;
                         var LADATA: array of ushort; Nth_Sample: uchar):
                         longint; stdcall; external 'E_l80.dll';

float SetUPPS1(float Voltage)

Here, it's strange. It seems like I set it correctly, however the function return is always 0, although it should be some other value. I used "extended" for the float type... I can see I set it correctly since another function gives me the current status, which changes with this setting...

function SetUPPS1(Voltage: extended): extended; stdcall; external 'E_l80.dll';

long SetupAWG(double *AnalogVoltage, short *DigitalData, long
BufferSize, double DCOffsetVoltage, double SampleFrequency, long Use4xGain, double
OutputImpedance, long Repeat,long Triggered, long OverrideOtherClocks)

AnalogVoltage: A pointer to an array of voltages;
DigitalData: A pointer to an array of digital data;

Here, same issue as above with arrays. However, based on the usage, I believe this arrays are the one to be sent, not received via parameter, therefore the "var" here might be wrong?

function SetupAWG(var AnalogVoltage: double; var DigitalData: short; BufferSize: longint; 
                      DCOffsetVoltage, SampleFrequency: double; Use4xGain: longint; 
                      OutputImpedance: double; Repeat_, Triggered: longint; 
                     OverrideOtherClocks: longint): longint; stdcall; external 'E_l80.dll';

Now, as you might see, I changed the types to Delphi equivalent, at least as far as I know I did it the right way.

If anyone knows answer to any of these things, or sees any mistake, I'd be glad to see that in comments/answers.

If I defined this bad, please point me to the right directions and give me a hint instead of comments about me being wrong. They kind of don't help... :/

Thanks a lot.

Upvotes: 1

Views: 434

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595349

It would be more useful to see the DLL's actual .h file instead of documentation, as documentation tends to not mention what the calling conventions actually are (and this case is no exception). You are declaring your Delphi functions as stdcall, which may or may not be correct. cdecl is another commonly used calling convention in DLLs, especially since it is C's default calling convention. So, if the functions are not declared with ANY explicit calling convention in the .h file, assume cdecl instead of stdcall. For this discussion, I will assume cdecl unless shown otherwise.

int SetAnalogChannels(int CH1Gain, int CH2Gain, bool CH1Couple, bool CH2Couple, bool CH1Multiplier, bool CH2Multiplier)

function SetAnalogChannels(CH1Gain, CH2Gain: Integer; CH1Couple, CH2Couple, CH1Multiplier, CH2Multiplier: Boolean): Integer; cdecl; external 'E_l80.dll';

long RetrieveDSOData(unsigned char whatchannels, double *DSOCH1, double *DSOCH2, unsigned short *LADATA, unsigned char Nth_Sample)

As the documentation says, these are pointers to arrays. I would translate them as-is, don't try to convert them to any fancy Delphi syntax:

function RetrieveDSOData(whatchannels: Byte; DSOCH1, DSOCH2: PDouble; LADATA: PWord; Nth_Sample: Byte): longint; cdecl; external 'E_l80.dll';

float SetUPPS1(float Voltage)

You converted this to Extended, which is wrong. Delphi's Single is equivalent to C's float:

function SetUPPS1(Voltage: Single): Single; cdecl; external 'E_l80.dll';

long SetupAWG(double *AnalogVoltage, short *DigitalData, long BufferSize, double DCOffsetVoltage, double SampleFrequency, long Use4xGain, double OutputImpedance, long Repeat,long Triggered, long OverrideOtherClocks)

Same as above for the arrays:

function SetupAWG(AnalogVoltage: PDouble; DigitalData: PShort; BufferSize: Longint; DCOffsetVoltage, SampleFrequency: Double; Use4xGain: Longint; OutputImpedance: Double; Repeat, Triggered, OverrideOtherClocks: Longint): longint; external 'E_l80.dll';

Upvotes: 2

Related Questions