使用 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]
属性对于结构类型是必需的,但对于原始类型则不是。
我正在尝试从 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
以下代码按缩进方式运行:
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]
属性对于结构类型是必需的,但对于原始类型则不是。