Delphi calling CVF dll

Delphi calling CVF dll

Hello everyone,

I've generated a dll using CVF ver 6.6. Everything seems to have gone correctly, and I have created a .dll, .exp and .lib files. I exported the function I want to call using the DLLEXPORT ATTRIBUTE and running DUMPBIN indicates I have, listing DESIGN as one of four exports. I want to call it from Delphi.

Here are function declaration and the call to load the library in Delphi

function design (var parm: Longint): Longint; stdcall; external 'design.dll';

hDLL := LoadLibrary ('design.dll');

and here's the declaration in Delphi of the call to the exported function (called design)

function design(var IntParm: IntArray; var RealParm: RealArray;
var RequestParm: RequestArray; var CharacterParm: CharacterArray;
var AuxParm1: CharacterArray; var AuxParm2: CharacterArray;
var AuxParm3: CharacterArray; var AuxParm4: CharacterArray;
var AuxParm5: CharacterArray; var AuxParm6: CharacterArray;
var AuxParm7: CharacterArray; var AuxParm8: CharacterArray;
var AuxParm9: CharacterArray): Longint; stdcall; external 'design.dll';

and finally here's the actual call

procedure CallDLL;
begin
try
DesignValue := design(IntArgs, RealArgs, RequestBfr, ChrctrBfr, AuxBuffer1,
AuxBuffer2, AuxBuffer3, AuxBuffer4, AuxBuffer5, AuxBuffer6, AuxBuffer7,
AuxBuffer8, AuxBuffer9);
except
on EMathError do
begin
DesignValue := 0;
MessageDlg ('floating point error trapped', mtError, [mbOK], 0);
end;
end
end;

The dll generated by Lahey Fortran LF95 works fine, but when I try to use the Compaq dll nothing happens. It appears the dll isn't being loaded.

Any suggestions?

Thanks,

Norm Clerman

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi Norm,

Several issues here:

1) You don't need to call LoadLibrary from Delphi. You may do it just to check whether hDll<>0, but otherwise Delphi automatically does it for you based on routine prototype.

2) What's the typedef of CharacterArray?

3) Case sensitivity. I discovered recently that Delphi is case-insensitive everywhere except on very declaration of dll routines. Based on your prototype, the export should be "_design@52". What's the export from Lahey dll? What's the export from CVF dll (I'd expect "_DESIGN@92")?

4) (And the most important) Hidden character arguments. If CharacterArray means what I expect (CHARACTER(LEN=*), DIMENSION(*)), CVF will expect an additional hidden argument for string length for every argument unless both STDCALL and REFERENCE for every string argument is specified. The appropriate set of attributes in CVF in your case should be:

INTEGER FUNCTION Design(IntParm, RealParm,...)
!DEC$ATTRIBUTES STDCALL, DLLEXPORT:: Design
!DEC$ATTRIBUTES REFERENCE:: CharacterParm
!DEC$ATTRIBUTES REFERENCE:: AuxParm1
...
!DEC$ATTRIBUTES REFERENCE:: AuxParm9
CHARACTER(LEN=AHardCodedValue):: CharacterParm

HTH
Jugoslav

Jugoslav
www.xeffort.com

Thank you Jugoslav!

The problem was the case sensitivity. I changed the function declaration in Delphi and everything worked fine.

For your information:

Lahey was exporting just design. (When you link a dll with the Lahey compiler you can specify that it's to be called by Delphi, and I imagine that's taking care of the name.) CVF was exporting both DESIGN and _DESIGN@52.

The typedef of CharacterArray is

CharacterArray = array[1..BFRLEN] of Char;

This is an array of bytes, and then over in the Fortran the corresponding argument is an array of size BFRLEN of one-byte integers. This requires some manipulation of the data on the Fortran side (because the data I'm passing is used as character data, not numeric), but it avoids the hidden arguments. It works fine.

Thanks again,

Norm

If you specify REFERENCE as I did above (but I think STDCALL is required as well -- but that will produce lowercase name) for these arguments, you can declare them as CHARACTERs and the hidden length will not be passed. However, that implies that length must be defined in some other way, either as an additional argument or a hard-coded value (BFRLEN). Your current solution with integer*1 arrays is also valid, but maybe using strings instead could be less tedious.

Btw, I discovered recently that Delphi feature with case-sensitivity accidentaly. I find it counter-intuitive -- it's like using Shift+Del in Explorer to delete the file permanently -- useful once you know it, but you'll hardly guess it yourself if someone doesn't tell you.

Jugoslav

Jugoslav
www.xeffort.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today