Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29230 Discussions

Delphi calling Fortran calling Delphi

dirkjan_eertink
Beginner
1,312 Views

The Delphi-program (see below) calls a procedure
DELPHICALLSFORTRAN(testfunc)
which resides in FtnLib3.DLL, compiled with Intel Visual Fortran 9.1.033 (IVF)
The parameter "testfunc" is a pointer and Delphi 'connects' that pointer to
a Delphi-procedure "testfunc".
On its turn, the Fortran-procedure DELPHICALLSFORTRAN "calls back" this function.

With Compaq Visual Fortran 6.5 (CVF) this went fine.
With IVF this produces an exception error:
'the instruction "0x00403102 referenced memory
at "0x011e2c20". The memory could not be "read"'
When the line "call DelphiLijn" (the "call-back") is left out, it runs perfect under both CVF and IVF.

Settings in Project / FtnLib3 properties... / Fortran / External Procedures:
calling convention = STCALL, REFERENCE
changing this into "C, REFERENCE" (both in Fortran and in Delphi) does not help.

What's wrong ?

Dirk Jan Eertink

======== the Fortran-code ================

! FtnLib3.f90
!
subroutine DELPHICALLSFORTRAN(testfunc)

!DEC$ ATTRIBUTES STDCALL, DLLEXPORT::DELPHICALLSFORTRAN
!DEC$ ATTRIBUTES ALIAS :'DELPHICALLSFORTRAN' :: DELPHICALLSFORTRAN
!DEC$ ATTRIBUTES REFERENCE :: testfunc

pointer (testfunc, DelphiLijn)

character thistime*8, thisdate*10

call date(thisdate)
call time(thistime)
open(6,file='testfile.txt',status='unknown',form='formatted')
write(6,'(4A)') ' Fortran (called by Delphi) made this file on ', thisdate, ' at ', thistime
close(6)

call DelphiLijn
stop

end subroutine DELPHICALLSFORTRAN

======== the Delphi-code ===============

unit delfiunit;

{
This program tests Delphi-programm calling a DLL, written in Fortran and
compiled with the Intel Visual Fortran 9.1.033 compiler.
This DLL contains a "call back": Delphi tells the Fortran-DLL the adress
of the Delphi-function "testfunc" and then the Fortran-DLL "calls back"
this Delphi-function.

This is working perfect when the Fortran part is compiled with the
Compaq Visual Fortran Compiler 6.5.
Compiling with the Intel Visual Fortran compiler 0.1.033 produces no
compilation messages, but running the Delphi-program produces a nasty error.
}

interface

uses
// windows, messages, variants,
// classes, graphics, controls, stdctrls,
sysutils, forms, dialogs;

type
tform1 = class(tform)
end;

var
form1: tform1;

implementation

{$R *.dfm}

// declaration of Fortran-routine:
procedure DelphiCallsFortran(var testfunc: pointer); stdcall; external 'ftnlib3.dll' name 'DELPHICALLSFORTRAN';

procedure testfunc; stdcall;
// this procedure will be called by the fortran-dll
var
f: textFile;
begin
showmessage(' success !');
end;

var
testfuncPointer : pointer;
begin
// tell the Fortran-routine "DELPHICALLSFORTRAN" the adress of
// the Delphi-routine "test":
testfuncPointer := @testfunc;
showmessage(' try to call ...');
DelphiCallsFortran(testfuncPointer);

end.

=====================================================

0 Kudos
3 Replies
Steven_L_Intel1
Employee
1,312 Views

Try removing the line:

!DEC$ ATTRIBUTES REFERENCE :: testfunc

0 Kudos
dirkjan_eertink
Beginner
1,312 Views
That's it !
So, by value, not by reference: I needed also to adapt the Fortran-settings from "STDCALL, REFENCE" to "STDCALL" and in the Delphi-source in "Procedure DELPHICALLSFORTRAN(var testfunc: stdcall)" to remove the "var " ("var" = by reference).
And it works. Now I'm going to test if this works also in de rather complicated "real world"/
Thanks a lot.



0 Kudos
Steven_L_Intel1
Employee
1,312 Views

Typically, when a procedure is passed, the address of the procedure is passed by value. (You can think of this as the procedure is passed by reference.) When you use the passed argument as an address, then you need to make sure that it is accepted as by value.

If you are passing other types of arguments which you're going to modify, then those have to be passed by reference.

DELPHI, like pretty much all of the "interpreted" languages on Windows, uses STDCALL as the default calling convention. How individual arguments are passed depends on how you declare them.

0 Kudos
Reply