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

Calling a Fortran dll with more than one array

esben_auken
Beginner
1,415 Views

Hi,

Can anyone direct me to an example where a subroutine in a Fortran dll is called with more than one array? I am calling form Delphi but a C example is as good.

I do not have problems passing a mixture of integers, reals and one array. When I try to pass two arrays I get an acces violation when I try to address array number two in the Fortran dll.

0 Kudos
7 Replies
Steven_L_Intel1
Employee
1,415 Views
What's the datatype of the array? Show us your Delphi and Fortran declarations of the routine. Unless you're passing character arrays, I can't think of a reason passing multiple arrays would be an issue.
0 Kudos
esben_auken
Beginner
1,415 Views

Thanks.

Here is the Delphi code:

var
Form1: TForm1;
procedure TestArray(Length: integer; AInteger: array of integer; RReal: Array of double); stdcall; external 'testdll.dll';
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
I : integer;
AInteger : array of integer;
AReal : array of double;
Length : integer;
begin
  //Transfer of integer and real arrays
Length:=4;
setlength(AInteger,Length);
setlength(AReal,Length);
for I:=0 to Length-1 do AInteger:=I;
for I:=0 to Length-1 do AReal:=I*3/2;
 TestArray(Length,AInteger,AReal)
end;

And here is the fortran code

subroutine TestArray(Length, AInteger,AReal)
!DEC$ ATTRIBUTES DLLEXPORT :: TestArray
!DEC$ ATTRIBUTES STDCALL :: TestArray
!DEC$ ATTRIBUTES ALIAS : 'TestArray' :: TestArray

implicit none
integer*4 Length
integer*4 AInteger(1)
real*8 AReal(1)

integer I

c-------Program
write(10,*) 'Program test1'
write(10,*) Length
do I=1,Length
write(10,*) AInteger(I)
end do
do I=1,Length
write(10,*) AReal(I)
end do
 write(10,*) 'End TestArray'

end subroutine TestArray

The first loop writing the AInteger array works but when AReal is written I get an access violation. The fort.10 file look like (this is what is written until it adresses the AReal array):

Program test1
4
0
1
2
3

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,415 Views
I'm not positive, but it seems that Delphi does to dynamic arrays the same thing as Fortran for strings (see J. Mansell's post here) -- it passes the length as a hidden argument. As a workaround, declare the arrays in Delphi as scalars by reference, and pass only the first element. That would explain why your single-array call (appers to have) worked (on the price of stack corruption), but the second array just grabs the wrong argument.
0 Kudos
esben_auken
Beginner
1,415 Views

Hi,

Thanks for your help.

I tried to change the Delpi code to:

procedure TForm1.Button1Click(Sender: TObject);
var
AInteger : array [1..4] of integer;
AReal : array [1..4] of double;
Length : integer;
begin
//Transfer of integer array
Length:=4;

for I:=1 to Length do AInteger:=I;
for I:=1 to Length do AReal:=I*3/2;
 TestArray(Length,AInteger[1],AReal[1])

but with the same result - I still gets an acces violation. I also tried to declare the array in the fortran code to assumed size

integer*4 :: AInteger(*)
real*8 :: AReal(*)

but that the same. Do you think I have to give it up?


					
				
			
			
				
			
			
			
			
			
			
			
		
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,415 Views
But did you change the dll declaration to:
procedure TestArray(Length: integer; var AInteger: integer; var RReal: double);
That ought to work. You can also print LOC(RReal) (RReal^) on Delphi and Fortran sides and see if they match.
0 Kudos
esben_auken
Beginner
1,415 Views

You are a hero - it works - thanks for your quick help.

Esben

0 Kudos
esben_auken
Beginner
1,415 Views

Just for your information - adjustable arrays in Delphi also works:

procedure TestArray(Length: integer; var AInteger: integer; var RReal: double); stdcall; external 'testdll.dll';
procedure TForm1.Button1Click(Sender: TObject);
var
I, J, LA :integer;
 AInteger : array of integer;
AReal : array of double;
Length : integer;
begin
//Transfer of integer and real array
Length:=4;
setlength(AInteger,Length);
setlength(AReal,Length);
for I:=0 to Length-1 do AInteger:=I;
for I:=0 to Length-1 do AReal:=I*3/2;
 TestArray(Length,AInteger[0],AReal[0])
end;

And in Fortran

subroutine TestArray(Length,AInteger,AReal)
!DEC$ ATTRIBUTES DLLEXPORT :: TestArray
!DEC$ ATTRIBUTES STDCALL :: TestArray
!DEC$ ATTRIBUTES ALIAS : 'TestArray' :: TestArray

implicit none
integer*4 Length
integer*4 :: AInteger(*)
real*8 :: AReal(*)

integer I

c-------Program
write(10,*) 'Program test1'
write(10,*) Length
do I=1,Length
write(10,*) AInteger(I)
end do
do I=1,Length
write(10,*) AReal(I)
end do
 write(10,*) 'End TestArray'

end subroutine TestArray

0 Kudos
Reply