使用 iFort 在 VS2019 中从 C# 调用 Fortran

Calling Fortran from C# in VS2019 with iFort

我正在尝试从 C# 调用 Fortran 代码。我正在使用 Visual Studio 2019 和英特尔 Fortran 编译器 (iFort)。

我用以下代码创建了一个 fortran DLL 项目,编译没有问题(项目设置为 'release'、'x64'):

module Fortran_DLL_Lib
    implicit none
contains
    subroutine adder(a,b,x,y)
        !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'adder' :: adder
        !DEC$ ATTRIBUTES REFERENCE :: x,y
        implicit none
        integer, intent(in) :: a,b
        integer, intent(out) :: x,y
        y = a + b
        x = 2*a+3*b
    end subroutine
end module

然后我使用以下代码创建了一个 C# 控制台应用程序(项目也设置为 'Release'、'x64'):

using System;
using System.Runtime.InteropServices;

namespace Call_Fortran_Dll_FromCS_Test
{
    class Program
    {
        [DllImport("Fortran_DLL_Lib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void adder(int a, int b, [Out] int x, [Out] int y);
        static void Main(string[] args)
        {
            int a = 4;
            int b = 3;
            int x = 0;
            int y = 0;
            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(x);
            Console.WriteLine(y);

            adder(a, b, x, y); //error occurs here
            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(x);
            Console.WriteLine(y);
            Console.ReadKey();
        }
    }
}

程序运行到调用fortran函数的那一行,然后returns报错

Exception thrown: 'System.DllNotFoundException' in Call_Fortran_Dll_FromCS_Test.dll
An unhandled exception of type 'System.DllNotFoundException' occurred in Call_Fortran_Dll_FromCS_Test.dll
Unable to load DLL 'Fortran_DLL_Lib.dll' or one of its dependencies: Access is denied. (0x80070005 (E_ACCESSDENIED))

我已将 'Fortran_DLL_Lib.dll' 和 'Fortran_DLL_Lib.lib' 文件复制到包含 c# 项目文件的文件夹中,以及可执行项目所在的位置,似乎都没有 help/matter.

这只是基于我发现的示例代码,试图找到执行此操作的方法,并不特定于我正在做的事情。在进入更复杂的应用程序之前,我只是想把 'proof of concept' 放在一起。该解决方案甚至不一定是 DLL,这正是我看到人们推荐的解决方案(在本网站上 7 年以上的问题中)。打开任何成功从 C# 项目调用 Fortran 代码的解决方案(如果重要的话,最终是具有 WPF GUI 的 C# 项目)。

我处于无法安装 Dependency Walker、更改环境变量或几乎任何需要提升权限的情况。

如有任何帮助,我们将不胜感激!

更新:对于 .NET Framework 和 .NET Core,下面@JAlex 的非常详尽和详细的回答非常有效。我的持续问题是由于我工作场所的用户帐户策略阻止了 运行 *.dll 文件(显然)。在正常的、不受限制的系统上尝试该解决方案完美无缺。

首先确保 dll 在 C# 驱动程序二进制文件旁边,将 dll 添加到 CSharp 解决方案中。使用 add-existing 和 然后添加为 link

然后select解决方案中的link如果更新

设置为复制

这会将 dll 放在输出文件夹中

此外,我将 Fortran 中的调用约定设置为 CVF,尽管我认为这是可选的,因为我明确指定了哪个参数是 REFERENCE 哪个是 VALUE.

我使用 dumpbin /exports

检查了 DLL 导出

以下代码按缩进方式运行:

Fortran 项目

请注意 VALUE 属性和 REFERENCE 属性的添加。

module mod_Fortran_dll
    use iso_c_binding
    implicit none
contains
    subroutine adder(a,b,x,y)
        !DEC$ ATTRIBUTES DLLEXPORT, alias:'adder' :: adder
        !DEC$ ATTRIBUTES VALUE :: a,b
        !DEC$ ATTRIBUTES REFERENCE :: x,y
        implicit none
        integer, intent(in) :: a,b
        integer, intent(out) :: x,y
        y = a + b
        x = 2*a+3*b
    end subroutine
end module

CSharp 项目

注意删除了 CDecl 调用约定,以及特定的 EntryPoint 规范。

static class Program
{
    #region Fortran
    [DllImport("FortranLib.dll", EntryPoint = "adder")]
    public static extern void adder(int a, int b, [Out] out int x, [Out] out int y);

    #endregion
    static void Main(string[] args)
    {
        int a = 4;
        int b = 3;
        int x = 0;
        int y = 0;

        Console.WriteLine($"a={a}, b={b}, x={x}, y={y}");
        // a = 4, b = 3, x = 0, y = 0

        adder(a, b, out x, out y);

        Console.WriteLine($"a={a}, b={b}, x={x}, y={y}");
        // a = 4, b = 3, x = 17, y = 7
    }
}

请注意,[Out] 属性对于结构类型是必需的,但对于原始类型则不是。