C # вызывает Fortran: 32-битный работает, 64-битный не может загрузить Fortran DLL - PullRequest
0 голосов
/ 19 февраля 2019

Я вставляю небольшой пример кода, который вызывает Fortran из C # ниже.Большая проблема, на которой основан этот небольшой воспроизводимый пример, была ранее опубликованной как 32-битная.В последнее время мне нужно, чтобы опубликованный код работал в 64-битном режиме, и именно тогда было обнаружено, что 64-битный код не работает.

Код разрабатывался в Visual Studio с установленным Intel Visual Fortran.Файл .sln содержит 2 проекта - C # в качестве «запускаемого проекта» и проект Intel Visual Fortran, который компилируется в виде DLL и вызывается проектом C #.На странице свойств файла .sln установка «Конфигурация» как 32-битной (x86) работала хорошо.Однако если вместо x64 используется как для C #, так и для Fortran, появляется следующее сообщение об ошибке:

System.DllNotFoundException: «Невозможно загрузить DLL» passStr_Fortran_C.dll ': указанный модуль не найден.(Исключение из HRESULT: 0x8007007E) '

Я надеюсь, что есть флаг или параметр, который просто необходимо переключить?Если это будет сложнее, я надеюсь, что кто-то сможет выложить изменения, которые должны произойти (возможно, с примером проблемы, приведенной ниже)?Вот два кода, которые составляют основу проектов C # и Fortran, которые работают с x86 (win32), но не с 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...