C# calling Fortran: 32-bit works, 64-bit unable to load fortran DLL

0

I'm pasting a small example code that calls Fortran from C# below. The larger problem on which this small reproducible example is based was previously published as 32-bit. More recently, I have need of getting the published code working in 64-bit, and that's when it was discovered that 64-bit is not working.

The code's development has been in Visual Studio, with Intel Visual Fortran installed. The .sln file has 2 projects - C# as the "startup project" and an Intel Visual Fortran project that is compiled as a DLL and called by the C# project. From the .sln file's properties page, setting the "Configuration" as 32-bit (x86) has worked well. However, if instead x64 is used for both the C# and Fortran, the following error message results:

System.DllNotFoundException: 'Unable to load DLL 'passStr_Fortran_C.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)'

My hope is that there is a flag or setting that simply needs to be toggled? If it is more complicated than that, my hope is that someone could lay out the modifications that need to take place (perhaps with the example problem provided below)? Here are the two codes that form the basis of the C# and Fortran projects that work with x86 (win32) but not x64.

C#:

using System;
using System.Runtime.InteropServices;

public static class Program
{
    public static int Nsegshold;
    public static double[] Diversions = new double[1];
    public static int Process_mode;

    //Fortran DLL interface
    [DllImport("passStr_Fortran_C.dll", CallingConvention = CallingConvention.Cdecl)]  //  CharSet = CharSet.Ansi, 
    public static extern void TEST_Var(ref int Process_mode, ref int Nsegshold, [In, Out] double[] Diversions);

    public static void Main(string[] args)
    {
        Process_mode = 1;
        Nsegshold = 1;
        TEST_Var(ref Process_mode, ref Nsegshold, Diversions);

        // Redimension arrays to size determined in fortran
        Diversions = (double[])ResizeArray(Diversions, new int[] { Nsegshold });

        Process_mode = 2;
        TEST_Var(ref Process_mode, ref Nsegshold, Diversions);

        Console.WriteLine("Two calls to fortran complete. ");
    }

    private static Array ResizeArray(Array arr, int[] newSizes)
    {
        if (newSizes.Length != arr.Rank)
            throw new ArgumentException("arr must have the same number of dimensions " +
                                        "as there are elements in newSizes", "newSizes");

        var temp = Array.CreateInstance(arr.GetType().GetElementType(), newSizes);
        int length = arr.Length <= temp.Length ? arr.Length : temp.Length;
        Array.ConstrainedCopy(arr, 0, temp, 0, length);
        return temp;
    }
}

Fortran:

!
    MODULE Fortran_C
!
    CONTAINS
!
    SUBROUTINE TEST_Var(Process_mode, Nsegshold, Diversions) BIND(C,NAME="TEST_Var")
!      
    !DEC$ ATTRIBUTES DLLEXPORT :: TEST_Var
!
    INTEGER, INTENT(IN)             :: Process_mode
    INTEGER, INTENT(INOUT)          :: Nsegshold
    DOUBLE PRECISION, INTENT(INOUT) :: Diversions(Nsegshold)
!
    INTEGER                         :: i
!
    IF(Process_mode.eq.1) THEN
      Nsegshold = 100
    ELSE IF(Process_mode.eq.2) THEN
      DO i = 1, Nsegshold
        Diversions(i) = 3.14 * i
      ENDDO
    ENDIF
!
    END SUBROUTINE TEST_Var
!
    END MODULE Fortran_C
c#
intel-fortran
asked on Stack Overflow Feb 19, 2019 by user2256085 • edited Feb 19, 2019 by Daniel A. White

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0