首页 > 编程语言 >C# Fortran混合编程

C# Fortran混合编程

时间:2024-03-20 17:14:13浏览次数:24  
标签:c# fortran C# double 编程 CallfuntoAdd dll Fortran ref

基本目标 : 利用c#调用 fortran中的 souroutine 或者 function 方法。通过把fortran 代码编译成 .dll (windows)/.so(unix) 动态库,放到 c# 的执行路径下。再通过 c# 中的DllImport 方法导入库函数,实现在 c# 中调用 fortran 方法。

1. DllImport 方法

该方法 来自 System.Runtime.InteropServices , 是由.Net提供的方法。例如可以使用下面的代码调用user32.dll中的MessageBox方法。

using System;
using System.Runtime.InteropServices;

MessageBox (IntPtr.Zero,"Please do not press this again.", "Attention", 0);

[DllImport("user32.dll")]
static extern int MessageBox (IntPtr hWnd, string text, string caption,
int type);

这里在c# 中声明方法的时候需要注意以下几点:

  1. 函数应该声明为 static, extern 方法
  2. 函数的参数类型需要注意,这里仅仅以fortran为例。下文介绍了几种常见参数传递的对应情况。

DllImport方法有几个参数也需要注意:

  1. EntryPoint:这需要使用一些第三方工具从dll / so 文件中查找。win下使用vs 带的 dumpbin.exe方法,使用dumpbin /EXPORTS target.dll 命令查看。linux 下使用 nm -D target.so 查找定义的方法的entrypoint。
  2. CallingConvention: 主要使用 CallingConvention.Cdecl 或者 CallingConvention.StdCall, 具体差别可以google.

2. c# 方法 与 Fortran 方法 参数对应

这里以示例代码来说明

module one
	implicit none
	abstract interface 
	    subroutine Add(b, c, a)
			implicit none
			integer b
			real*8 a
			dimension a(*)
			real*8 c
		end subroutine
	end interface
contains
	subroutine CallfuntoAdd(f, b, c, a)
		!DEC$ ATTRIBUTES ALIAS:'CallfuntoAdd' :: CallfuntoAdd
        !DEC$ ATTRIBUTES DLLEXPORT :: CallfuntoAdd
        !DEC$ ATTRIBUTES reference :: f, a, b, c
		implicit none
		real*8 c
		integer b
		real*8 a
		dimension a(*)
		
        procedure(Add)::f
		Call f(b, c, a)
	    write(*,*) " c = ", c
		return
	end subroutine
end module one

在上面的Fortran代码里定义了一个CallfuntoAdd(f, b, c, a)方法,可以通过!DEC$被导出到 dll 文件中。这里f 是一个回调函数, b 是integer类型, c是real*8类型, a 是一个一维数组。

public class c1
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void AddFunc(ref int b, ref double c, [In] IntPtr a);

        public static void Add1(ref int b, ref double c, [In] IntPtr a)
        {
            double[] a1 = new double[b];
            Marshal.Copy(a, a1, 0, b);
            c = 0;
            for (int i = 0; i < b; i++)
            {
                c += a1[i];
            }
        }

        [DllImport("mod1.dll", EntryPoint = "__one_MOD_callfuntoadd", CallingConvention = CallingConvention.Cdecl)]
        public static extern void CallfuntoAdd([MarshalAs(UnmanagedType.FunctionPtr)] AddFunc f, ref int b, ref double c, double[] a);

        public static void Main()
        {
            double c;
            double[] a = new double[3] { 3.0, 2.0, 4.0 };
            int b = a.Length;
            c = 0;

            CallfuntoAdd(Add1, ref b, ref c, a);
            Console.WriteLine($" c = {c}");
        }
    }

上面的c# 代码定义了一个CallfuntoAdd函数用来表示 fortran中的CallfuntoAdd方法。这c# 的函数名可以通过fortran 中 !DEC$ ATTRIBUTES ALIAS:'CallfuntoAdd' :: CallfuntoAdd 重新定义。在c#中使用委托来表示fortran中的回调函数。可以看到c# 中的CallfuntoAdd函数参数与 fortran中的CallfuntoAdd 函数参数的对应关系。

fortran c#
integer ref int
real*4 ref float
real*8 ref double
一维数值 real*8, dimension(

标签:c#,fortran,C#,double,编程,CallfuntoAdd,dll,Fortran,ref
From: https://www.cnblogs.com/hugowu-blog/p/18085641

相关文章

  • 7、docker-compose安装使用
    ##下载docker-composecurl-Lhttps://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname-s`-`uname-m`>/usr/local/bin/docker-compose##可选升级包curl-L"https://github.com/docker/compose/releases/download/v2.11.0/docker-compose-......
  • 8、docker swarm操作使用
    #集群初始化dockerswarminit#查看集群节点dockernodels#获取加入集群的tokendockerswarmjoin-tokenworkerdockerswarmjoin-tokenmanager#查看#改变节点可用性:Active:调度程序可以将任务分配给当前节点。Pause:调度程序不会将新任务分配给当前节点,但现有任务仍......
  • 面试题 17.12. BiNodec
    /***Definitionforabinarytreenode.*structTreeNode{*intval;*structTreeNode*left;*structTreeNode*right;*};*/structTreeNode*convertBiNode(structTreeNode*root){if(!root)returnNULL;if(!root->left......
  • spring的IOC
    IOC翻译成中文是"控制反转",不是具体技术,而是实现对象解耦的思想。控制反转的意思是将依赖对象生命周期控制权进行反转,全称应该是控制权反转。之前需要一个对象,常用的方法就是在当前对象中new一个对象,那这样有个比较大的问题在于,耦合,一旦new的那个对象构造方法变动,那么所有使用到......
  • 1、安装docker引擎
    一、安装Docker设置centosyum镜像源cd/etc/yum.repos.d/mkdirbackup&&mv*repobackup/wget-O/etc/yum.repos.d/CentOS-Base.repohttps://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repoyumcleanall&&yummakecacheyumrepolistall卸载旧版本......
  • 2、docker镜像操作
    #列出本地镜像->dockerimages#拉取镜像->dockerpullregistry:2.4.1#删除镜像->dockerrmiregistry:2.4.1#导出镜像->dockersave-ojenkins.tar.gzjenkins/jenkins#导入镜像->dockerload-ijenkins.tar.gz#修改本地镜像->dockerrun-t-iregistry......
  • 4、docker仓库操作
    一、拉取仓库镜像->dockerpullregistry:latest二、启动仓库镜像->dockerrun-d-p5000:5000--nameregistry--restart=always-v/opt/registry-var/:/var/lib/registry/registry:latest三、标记镜像->dockertag[镜像id:tag]127.0.0.1:5000/test四、上传到私......
  • 3、docker容器操作
    #列出所有docker容器->dockerps-a#启动docker容器(以启动仓库容器为例)#-d表示后台运行容器,-p表示端口绑定#--name表示给该容器命名为registry,在启动、停止、重启、删除时方便使用#--restart=always表示该容器在docker服务启动时自动重启#-v参数表示将/opt/registry-var/......
  • Elasticsearch-Mapping映射
    Mapping映射自动或手动为index中的_doc建立一种数据结构和相关配置动态映射:dynamicmapping,自动为我们建立index,以及对应的mapping,mapping中包含了每个field对应的数据类型,以及如何分词等设置。PUT/web_site/_doc/1{"post_date":"2023-01-01","title":"Thelonger",......
  • LCR 159. 库存管理 IIIc
    /***Note:Thereturnedarraymustbemalloced,assumecallercallsfree().*/intdivide(int*stock,inthead,inttail){intt=stock[head];while(head<tail){while(head<tail&&stock[tail]>t)tail--;if(head<......