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

Calls to fseek and ftell not working from C#

Ruben_P_
Beginner
464 Views

Hi all,

I'm writing some fortran code to read Nastran op2 files. I am using fseek and ftell to store the position of certain data blocks. This code is compiled to a DLL and called either from C++ code or C# code. When I call the function from c++ fseek/ftell works correctly, but when called from C# using PInvoke both return always -1. Am I missing something?

C# code:

[DllImport("mydll.dll", EntryPoint = "abcd", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.I4)]
static extern int abcd([param: MarshalAs(UnmanagedType.I4)] Int32 dummyInt);

int d1=abcd(4);

Fortran DLL code:

function abcd(input) result(istat)
!DEC$ ATTRIBUTES ALIAS:'abcd' :: abcd
!DEC$ ATTRIBUTES DLLEXPORT :: abcd
!DEC$ ATTRIBUTES VALUE :: input

    use ifport
    integer,intent(in) :: input

    integer(4) istat, offset, ipos, posactual, res
    integer :: f
    
    f=1
    OPEN (UNIT=f, IOSTAT=ios, ERR=100, FILE='C:/test.op2', form='unformatted', STATUS='OLD', ACTION='READ')
    
    READ (f, END=100) res
    res=fseek(f, 10, 0)
    istat=ftell(f)

100 end function abcd

 

0 Kudos
7 Replies
jimdempseyatthecove
Honored Contributor III
464 Views

First thing to resolve is if  which function failed or if the C# interface is wrong.

At line 11 above insert istat=999111
At line 14 above insert istat=999222
At line 18 above, insert istat=123456

Then see what the return is to C#.

999111 indicates open fail,
999222 indicates read fail,
123456 indicates success (though value you do not want)
-1 indicates something wrong with interface.

By the way, you will need to set in your own error codes at lines 11 and 14. Currently you would return uninitialized data.

Jim Dempsey

0 Kudos
Ruben_P_
Beginner
465 Views

Thanks jimdempseyatthecove for your response. I get 123456 as return, but my problem is that I cannot place the file pointer where I want using fseek. I have tried INQUIRE(UNIT=f, POS=ipos)  but the position does not change after seeking 10 positions.

0 Kudos
jimdempseyatthecove
Honored Contributor III
465 Views

Describe the contents of test.opt2

What is the value of res following fseek?

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
465 Views

The c# declares the procedure to be stdcall, but there is no visible corresponding declaration in the Fortran source.

Which compiler are you using?  What compile options are you using?  If you are using Intel Fortran without some sort of compile option to specify stdcall - then you have a calling convention mismatch.

I strongly recommend using the C interoperability features for Fortran 2003 for interoperating with other languages that know the relevant C calling convention.

0 Kudos
Ruben_P_
Beginner
465 Views

The value of res after line 16 is -1. 

I have tried changing calling convention to cdecl in the C# dllimport or adding !DEC$ATTRIBUTES STDCALL :: abcd to the fortran function, but the result is the same.

The compiler is Intel Fortran 16.0 for Windows with these options:

/nologo /debug:full /Od /warn:interfaces /module:"x64\Debug\\" /object:"x64\Debug\\" /Fd"x64\Debug\vc120.pdb" /traceback /check:bounds /check:stack /libs:dll /threads /dbglibs /c

0 Kudos
JohnNichols
Valued Contributor III
465 Views

I have tried C# to Fortran -- you may as well take a long holiday in Nepal -- it is very difficult and leads to enormous frustration.

0 Kudos
Greg_T_
Valued Contributor I
465 Views

Hi Ruben,

We've had good success calling Fortran subroutines from C# for FEA result post processing and returning scalar and array values, so it is possible.  While you are working on the calling conventions, perhaps a comparison to the syntax we're using would help.  Some differences that I see in our syntax is that in the C# code I only specified the DLL name, am using "static extern void" to call the subroutine, and am passing arrays by reference to return values from Fortran to C#, for example:

        [DllImport("myfortran.dll")]
        static extern void mysub1(ref int arraySize, int[] myIntArray, double[,] myRealArray);

I think arrays are passed by reference by default ("ref" not needed), and passing scalars would need to have the "ref" statement added.  Does it make calling Fortran any easier to use  "void" instead of returning an integer?  Could the integer be returned as one of the parameters?

The syntax in the Fortran look similar, except we're using the "REFERENCE" attribute:

!DEC$ATTRIBUTES REFERENCE :: arraySize, myIntArray, myRealArray

Regards,
Greg

        
0 Kudos
Reply