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

C# call of Fortran routine with arrays

Wagner__Urs
Novice
685 Views

I hope You can help me.

I would like to use this Fortran subroutine:

 

SUBROUTINE AKIMA (N,XI,YI,I1,X,Y)
!
!DEC$ ATTRIBUTES DLLEXPORT :: Akima
!DEC$ ATTRIBUTES VALUE :: N
!DEC$ ATTRIBUTES VALUE :: X

 

INTEGER IN, I1

REAL X,XI(1),YI(1),Y(3)

...

END

 

In C# I use this definition.

[DllImport("FortLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void akima(
int n,
[MarshalAs(UnmanagedType.LPArray)] double[] xi,
[MarshalAs(UnmanagedType.LPArray)] double[] yi,
ref int index,
double x,
[MarshalAs(UnmanagedType.LPArray)] double[] y);

 

1) I get an error like this

System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>

 

2) How to do this with 64Bit. I works only with 32 Bit.

0 Kudos
1 Solution
Steve_Lionel
Black Belt
665 Views

I see other problems. On Windows, where this is obviously being run, the Fortran routine name will be AKIMA in uppercase, but the C# name is akima and C# is case-sensitive.

The use of (1) as an array dimension is an old F66 trick back before the days of array bounds checking. The correct way to declare such arrays nowadays is ( * ).

May I suggest the following rewrite?

SUBROUTINE AKIMA (N,XI,YI,I1,X,Y) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
!
!DEC$ ATTRIBUTES DLLEXPORT :: AKIMA
INTEGER(C_INT), VALUE, INTENT(IN) :: N
REAL_C_DOUBLE), INTENT(INOUT) :: XI(*), YI(*)
INTEGER(C_INT), VALUE, INTENT(IN) :: I1
REAL(C_DOUBLE), VALUE, INTENT(IN) :: X
REAL(C_DOUBLE), INTENT(INOUT) :: Y(3)

...

END

View solution in original post

0 Kudos
6 Replies
Arjen_Markus
Honored Contributor I
673 Views

I am not sure this is the only problem (I prefer to use the standard features of  Fortran rather than compiler directives), but you pass in an array of double-precision reals, whereas the Fortran routine expects single-precision reals.

Also, the declaration of XI and YI looks like this is old code - or does the routine really only use the first element from both arrays?

Any idea if the Fortran routine does anything at all or does it crash right away?

0 Kudos
Steve_Lionel
Black Belt
666 Views

I see other problems. On Windows, where this is obviously being run, the Fortran routine name will be AKIMA in uppercase, but the C# name is akima and C# is case-sensitive.

The use of (1) as an array dimension is an old F66 trick back before the days of array bounds checking. The correct way to declare such arrays nowadays is ( * ).

May I suggest the following rewrite?

SUBROUTINE AKIMA (N,XI,YI,I1,X,Y) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
!
!DEC$ ATTRIBUTES DLLEXPORT :: AKIMA
INTEGER(C_INT), VALUE, INTENT(IN) :: N
REAL_C_DOUBLE), INTENT(INOUT) :: XI(*), YI(*)
INTEGER(C_INT), VALUE, INTENT(IN) :: I1
REAL(C_DOUBLE), VALUE, INTENT(IN) :: X
REAL(C_DOUBLE), INTENT(INOUT) :: Y(3)

...

END
0 Kudos
JohnNichols
Valued Contributor III
662 Views

Whenever I need a new C# to Fortran I start here, I just checked it - it is still working.  

Your biggest problem is not Fortran it is the frequent C# updates and SDK changes.  

 

Good luck. 

0 Kudos
Wagner__Urs
Novice
614 Views

Thanks for the sample, it helps!

0 Kudos
Wagner__Urs
Novice
614 Views

Yes it is code from the eighties, I will modernize it.

0 Kudos
FortranFan
Honored Contributor II
632 Views

@Wagner__Urs ,

The advice by @Steve_Lionel is something you may want to closely consider.

Also, see this thread: https://community.intel.com/t5/Intel-Fortran-Compiler/Passing-2D-array-to-C-app-results-in-memory-access-violation/m-p/1131561/highlight/true#M134440

The above gives you a fully worked out example of a somewhat more involved case of a rank-2 array of a struct datatype that will function in a 64-target or 32-bit without any code changes.  You can consider applying the learnings and the example toward your situation.

0 Kudos
Reply