[英]Calling Fortran from C# in VS2019 with iFort
I am trying to call Fortran code from C#.我正在尝试从 C# 调用 Fortran 代码。 I am using Visual Studio 2019 and the Intel Fortran Compiler (iFort).
我正在使用 Visual Studio 2019 和英特尔 Fortran 编译器 (iFort)。
I created a fortran DLL project with the following code that compiles without issue (project set to 'release', 'x64'):我使用以下代码创建了一个 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
I then created a C# console application with the following code (project also set to 'Release', 'x64'):然后,我使用以下代码创建了一个 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();
}
}
}
The program runs up until the line that calls the fortran function, then returns the error程序一直运行到调用fortran函数的那一行,然后返回错误
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))
I have copied both the 'Fortran_DLL_Lib.dll' and 'Fortran_DLL_Lib.lib' files into both the folder that contains the c# project files, as well as the location where the executable project is located, neither seems to help/matter.我已将 'Fortran_DLL_Lib.dll' 和 'Fortran_DLL_Lib.lib' 文件复制到包含 c# 项目文件的文件夹以及可执行项目所在的位置,似乎都无济于事。
This is just based on example code I found trying to find ways to do this and isn't specific to what I'm doing.这只是基于我在尝试寻找方法时发现的示例代码,并不特定于我正在做的事情。 I'm just trying to get a 'proof of concept' together before jumping into more complex applications.
在跳入更复杂的应用程序之前,我只是试图将“概念证明”放在一起。 The solution doesn't even necessarily be a DLL, that's just what I saw people recommending as the solution to this (in 7+ year old questions on this site).
解决方案甚至不一定是 DLL,这正是我看到人们推荐的解决方案(在本网站上 7 年以上的问题中)。 Open to any solutions that successfully call Fortran code from a C# project (eventually, a C# project with a WPF GUI, if that matters).
对从 C# 项目(最终,具有 WPF GUI 的 C# 项目,如果重要的话)成功调用 Fortran 代码的任何解决方案开放。
I am in a situation where I can't install Dependency Walker, change environment variables, or pretty much anything that requires elevated privileges.我处于无法安装 Dependency Walker、更改环境变量或几乎任何需要提升权限的情况。
Any help would be greatly appreciated!任何帮助将不胜感激!
a
and b
are still reference arguments, unless you add the VALUE
attribute in their definition in Fortran. a
和b
仍然是引用参数,除非您在 Fortran 中的定义中添加VALUE
属性。
So in C# you need to change your declaration to因此,在 C# 中,您需要将声明更改为
public static extern void adder(ref int a, ref int b, out int x, out int y);
Note that the [Out]
attribute is required for structure types, but not for primitive types.请注意,结构类型需要
[Out]
属性,但基本类型不需要。
Also to make sure the dll
is next to the C# driver binary, add the dll into the CSharp solution.还要确保
dll
位于 C# 驱动程序二进制dll
旁边,请将 dll 添加到 CSharp 解决方案中。 Use add-existing and then add as link使用 add-existing然后添加为链接
then select the link in the solution and set to copy if newer然后选择解决方案中的链接并设置为如果更新则复制
this will place the dll in the output folder这会将 dll 放在输出文件夹中
additionally, I set the calling convention in Fortran as CVF, although I think this is optional as I specify explicitly which argument is REFERENCE
and which is VALUE
.此外,我将 Fortran 中的调用约定设置为 CVF,尽管我认为这是可选的,因为我明确指定了哪个参数是
REFERENCE
,哪个是VALUE
。
I checked the DLL export using dumpbin /exports
我使用
dumpbin /exports
检查了 DLL 导出
The following code works as indented:以下代码按缩进方式工作:
Note the addition of the VALUE
attributes as well as the REFERENCE
ones.请注意
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
Note the removal of the CDecl
calling convention, and the specific EntryPoint
specification.请注意
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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.