首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从c#中调用函数更改fortran中的参考参数值

从c#中调用函数更改fortran中的参考参数值
EN

Stack Overflow用户
提问于 2019-08-13 12:51:40
回答 2查看 256关注 0票数 0

我有一个用fortran编写的dll,其中包含一个以逻辑参数作为输入的子例程。我希望使用它来控制子例程的取消,并且有可能在调用c#代码中更改它的值。下面是我测试过的一个小例子。

C#代码:

代码语言:javascript
复制
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace TestConsApp
{
    internal static class Program
    {
        private static bool _b;
        [DllImport(dllName: "TestFortran.dll", CallingConvention = CallingConvention.Cdecl)]
        internal static extern void TestBool(ref bool b);


        private static void Main(string[] args)
        {    
            TestFortranBool();
            Console.ReadLine();
        }


        private static void TestFortranBool()
        {
            _b = true;
            var t = Task.Factory.StartNew(() => TestBool(ref _b));
            Console.WriteLine($"C# :{_b}");
            Thread.Sleep(5000);
            _b = false;
            Console.WriteLine($"C# :{_b}");
            Thread.Sleep(5000);
            _b = true;
            Console.WriteLine($"C# :{_b}");
            Thread.Sleep(5000);
            _b = false;
            Console.WriteLine($"C# :{_b}");
            Thread.Sleep(5000);
            _b = true;
            Console.WriteLine($"C# :{_b}");

            t.Wait();
        }
    }
}

和fortran代码:

代码语言:javascript
复制
module FortranTesting
  use iso_c_binding
  implicit none
contains
  
  
  subroutine TestBool(b)

  ! Expose subroutine TestFortran to users of this DLL
  !
  !DEC$ ATTRIBUTES DLLEXPORT::TestBool
  !DEC$ ATTRIBUTES DECORATE,ALIAS:"TestBool" :: TestBool
  
  logical(c_bool),intent(in) ::  b
  write(*,*) "Inside fortran"
  write(*,*) "F :", b
  call sleep(5)
  write(*,*) "F : ", b
  call sleep(5)
  write(*,*) "F : ", b
  call sleep(5)
  write(*,*) "F : ", b
  
  end subroutine TestBool
end module FortranTesting

我从中得到的是:

C#:真 内福特兰 F:T C#:假 F:T C#:真 F:T C#:假 F:T C#:真

我想要的是F (fortran)与C#交替使用。在从C#读取变量和在Fortran中更改变量时,我尝试了相反的方法,而Fortran的工作原理是预期的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-22 12:52:59

我终于找到了解决取消的办法。我给出了一个示例代码,它向fortran代码返回一个值(因此可以用来取消fortran子例程/函数):

c#代码:

代码语言:javascript
复制
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestConsApp
{
    internal static class Program
    {
        [DllImport(dllName: "TestFortran.dll", CallingConvention = CallingConvention.Cdecl)]
        internal unsafe static extern void TestCallBack([MarshalAs(UnmanagedType.FunctionPtr)] ActionRefInt callBack);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void ActionRefInt(ref int i);


        private static void Main(string[] args)
        {
            TestCallBack();
            Console.ReadLine();
        }

        private static void TestCallBack()
        {
            var callbackHandler = new ActionRefInt(OnCallBackInt);
            TestCallBack(callbackHandler);
        }

        private static void OnCallBackInt(ref int i)
        {
            Console.WriteLine($"C#: Value before change: {i}");
            i++;
            Console.WriteLine($"C#: Value after change: {i}");
        }

    }
}

和Fortran代码:

代码语言:javascript
复制
  module FortranTesting
  use iso_c_binding
  implicit none

  contains

  subroutine TestCallBack(callBack)
  !DEC$ ATTRIBUTES DLLEXPORT::TestCallBack
  !DEC$ ATTRIBUTES DECORATE,ALIAS:"TestCallBack" :: TestCallBack
  external        ::  callBack
  integer         ::  test
  
  test  = 1
  write(*,*) "F: Test before callback: ", test
  call callBack(test)
  write(*,*) "F: Test after callback: ", test
  end subroutine TestCallBack
  end module FortranTesting

此代码产生以下输出:

F:回调前的测试:1 C#:变化前的价值:1 C#:更改后的值:2 F:回调后的测试:2

票数 0
EN

Stack Overflow用户

发布于 2019-08-13 23:22:44

我不认识C#,所以我不能帮你。但是,只要您可以将C#与C接口,也有一种方法可以将Fortran代码连接到C#。为此,必须将bind(C)属性添加到Fortran代码中,

代码语言:javascript
复制
module FortranTesting
    use iso_c_binding
    implicit none
contains
    subroutine TestBool(b) bind(C, name = "TestBool")
        ! Expose subroutine TestFortran to users of this DLL
        !DEC$ ATTRIBUTES DLLEXPORT :: TestBool

        use, intrinsic :: iso_c_binding, only: c_bool
        implicit none
        logical(c_bool), intent(in) ::  b

        write(*,*) "Inside Fortran:"
        write(*,*) "F :", b
        call sleep(5)
        write(*,*) "F : ", b
        call sleep(5)
        write(*,*) "F : ", b
        call sleep(5)
        write(*,*) "F : ", b

    end subroutine TestBool
end module FortranTesting

这段代码现在应该可以从C调用为TestBool(b),并带有一个具有_Bool类型的输入参数b

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57478125

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档