Silverfrost Forums

Welcome to our forums

Strange iostat value returned by open

21 Jun 2014 7:15 #14251

The open statement shown lives in some code which can be built into either a .exe or a DLL. The open behaves as expected when running the .exe and returns a iostat of 0 in normal circumstances (the file exists and is not open elsewhere).

open(32, file='file.bin', form='unformatted', access='transparent', status='old', iostat=ios)

Sometimes, when the code is running as a DLL (invoked by a C# .NET process), an iostat value of 1 comes back. This result is consistent in that if I run the test again the same iostat value is returned. It also seems spurious in that if I make a completely unrelated change to some other part of the code, the problem can go away, only to return again later when I make some other unrelated change to some other part of the code.

Apart from asking for ideas on how I can investigate this further, I do have two specific questions:

  1. Is there a genuine set of circumstances in which this open can return an iostat value of 1? According to FTN95 help this code translates to 'Floating point arithmetic over flow'.

  2. Are there some rules and guidelines I ought to be aware of in order to get a FORTRAN DLL involving I/O to work reliably when invoked by a .NET process?

Thanks, John

22 Jun 2014 6:49 #14252

My first guess would be that an iostat of 1 means 'Invalid function' but then I would not know how that might arise.

More likely there is a problem with garbage collection - i.e. memory is not being locked and you are getting a spurious error report. This would mean that DBK_LINK is not working as it should in this context.

If everything is working OK (despite this IOSTAT value) thenI would be tempted to carry on regardless. However, if you would like us to try to sort it out then we would need a short sample program that illustrates the issue.

22 Jun 2014 8:39 #14253

Thanks for your comments Paul.

Please expand on your comment about memory not being locked. I am not (knowingly) using multi-threading. I have made sure that all modules that declare data at the outer level have a save directive.

The overall setup is like this:

A 32-bit C# .exe dynamically loads a 32-bit C# .dll that provides a wrapper for entry points in the FORTRAN dll. This is all built with Visual Studio Express.

The FORTRAN dll is produced in Plato as a Win32 Release build with no non-default settings.

22 Jun 2014 8:55 #14254

I am suggesting that there might be a fault in DBK_LINK (the FTN95 linker for .NET). One of the things that DBK_LINK does is to lock memory for Fortran linking with C# etc. .NET has automatic garbage collect which means that, by default, objects are not fixed in memory. Traditionally Fortran uses a fixed memory system and DBK_LINK responds to this dilemma by locking the Fortran part.

It is also possible that your C# coding has not taken account of garbage collection. i.e that you have assumed objects (passed to Fortran) are always fixed in memory.

22 Jun 2014 3:52 #14255

The only 'objects' being passed across the interface are:

integer (passed both ways) double (passed both ways) string (only passed from C# to FORTRAN) vector of double (passed both ways)

Unfortunately I have only seen the problem I have reported in the large body of code that is the real application. I have today seen a variant of the problem where instead of the unexpected result code from the binary file open there is a crash on the first open of a .txt file. I have also now built the dll using gFORTRAN and that works OK so far.

The number of interface calls made before the crash in the above two cases is quite limited. The interface code I am using on both the C# side a the FORTRAN side is not something I made up but has been used by others with Intel FORTRAN. What is the best way to make progress on this problem?

Thanks, John

22 Jun 2014 6:25 #14256

Your use of gFortran raises the question... when compiling with FTN95, are you using .NET (i.e. /CLR on the command line)?

23 Jun 2014 10:45 #14259

The project is set for Release Win32 builds in Plato, which is where I do all FTN95 builds. I think that means I am avoiding .NET on the FORTRAN side. That is a requirement for the project.

This is how one of the entry points is defined in the FORTRAN code:

subroutine XXXX_ENGINE_INITIALISE(args, success_code) !DEC$ ATTRIBUTES DLLEXPORT :: XXXX_ENGINE_INITIALISE !DEC$ ATTRIBUTES ALIAS:'_XXXX_ENGINE_INITIALISE' :: XXXX_ENGINE_INITIALISE character(*), intent(in) :: args integer, intent(out) :: success_code ! 0: ok, -ive fatal error, +ive warning

The above is used with C# calling code like:

    [DllImport(ExternalDll_C.Filename,
        EntryPoint = 'XXXX_ENGINE_INITIALISE',
        ExactSpelling = false,
        CallingConvention = CallingConvention.Cdecl)
    ]
    internal static extern void XXXX_ENGINE_INITIALISE(
        [MarshalAs(UnmanagedType.LPStr)] StringBuilder inString,
        ref int successCode, // 0: ok, -ive fatal error, +ive warning
        int inStringLength);
23 Jun 2014 1:59 #14261

I doubt if anyone has tried to do this before.

FTN95 has a .NET mode that is designed for running alongside other .NET assemblies. What you are attempting may well work at times but I cannot say that it is supported.

It is true that you can access a Win32 DLL from a .NET assembly but the assumption will be that the DLL does not have its own semi-permanent store (i.e. storage that is preserved between function calls). This is not the case for an FTN95 DLL because it accesses salflibc.dll (e.g. for IO).

I suggest that you try creating an FTN95 DLL in the form of a .NET assembly. This may be just a case of selecting .NET mode in Plato.

26 Jun 2014 9:00 #14272

Thanks for your comments.

Having found that my recent FTN95 Express install had made changes to PATH that resulted in use of an older version of both the compiler and library instead of the version 7.1 I thought I was using, and having fixed the PATH problem, the OPEN failure symptoms have gone away.

Since fixing the PATH problem, my experience is that invoking Win32 FTN95 in the manner described, works (at least to the extent that it does not fall over). I have tried both a simple setup involving one sub-process and a more complex case like this:

Controlling process in C# Sub-process1 in C# calling FTN95 Win32 DLL Sub-process2 in C# calling FTN95 Win32 DLL

The two sub-processes both make extensive use of FORTRAN I/O.

I note your reservations, and will try compiling the FORTRAN as .net.

Please login to reply.