Stupid && 祖传Fortran代码救赎之路(编译Dll)
Stupid && 祖传Fortran代码救赎之路(编译Dll)
gfortran编译动态库
在Windows平台下,Intel Fortran安装过于庞大且费事(现在集成到OneAPI上了,安装下需要60G),之前在VS2019上折腾了好久,最后Debug调试不显示过程变量,吐了。。。
后来决定直接用gfortran+gdb+VScode来做Fortran程序的调试与编译。在此记录一下,如何时使用gfortran编译Dll,以及如何使用C++、Matlab调用Fortran生成的Dll库。
Fortran测试程序(test.f90)
各种不同的Fortran源程序定义接口的方法看到过不少,比如传送门。
最后发现以下这种方式最为简单,且有效,具体为啥我也不清楚。
测试程序中test1()没有输入输出,test2(array,Num)需要返回一个数组(Fortran函数大都需要数组作为输入输出)。
subroutine test1() BIND(C,NAME="test1")
  implicit none
  PRINT *, 'I am a function'
  return
end 
subroutine test2(array,Num)  BIND(C,NAME="test2")
  implicit none
  INTEGER,INTENT(IN):: Num
  REAL*8,INTENT(OUT):: array(1:Num)
  INTEGER :: I
  DO I=1,Num
    array(I)=I
  ENDDO
end
编译命令
编译成为动态库
> gfortran -c -O3 f90
> gfortran -shared -static -o Test.dll *.o
编译完成即可得到名为\(Test.dll\)的动态链接库
C++调用Fortran动态库(DLL)
采用显示调用的方式调用动态库,在Windows平台下,借助\(Windows.h\)中的\(LoadLibrary,GetProcAddress,FreeLibrary\)动态加载,使用动态库。
测试程序
#include <iostream>
#include <Windows.h>
using namespace std;
typedef void(*test1Func)();
typedef void(*test2Func)(double*, int*);
int main(void)
{
	//加载DLL库
	HINSTANCE hDLL = LoadLibrary(L"Test.dll");
	//定义函数指针
	test1Func test1;    // Function pointer
	test2Func test2;
	if (hDLL != NULL)
	{
		//获得函数地址
		test1 = (test1Func)GetProcAddress(hDLL, "test1");
		test2 = (test2Func)GetProcAddress(hDLL, "test2");
		if (!test1 && !test2)
		{
			// handle the error
			std::cout << "Open the dll error" << std::endl;
            //卸载函数库
			FreeLibrary(hDLL);
			return -1;
		}
		else
		{
			test1();
			int Num = 10;
			double* myarray = new double[Num];
			test2(myarray, &Num);
			for (int i = 0; i < Num; ++i)
				cout << myarray[i] << endl;
			FreeLibrary(hDLL);
		}
	}
	return 0;
}
输出
 I am a function
1
2
3
4
5
6
7
8
9
10
Matlab 调用.DLL
现在已经得到gFortran编译的Dll库,在Matlab中,可以使用calllib方法调用函数,但是需要存在函数声明,所以首先编写C头文件,存放函数声明。
函数声明头文件
//Test.h
void test1();
void test2(double*,int * );
Matlab Demo
clc;clear all;
loadlibrary('Test.dll','Test.h');
% test1 函数没有参数,也没有返回值,不知道咋调用
% calllib('Test','test1');
Num=10;
myarray=zeros(Num,1);
[myarray,NN]=calllib('Test','test2',myarray,Num);
myarray
NN
unloadlibrary Test
输出结果
myarray =
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
NN =
  int32
   10
参考链接
Stupid && 祖传Fortran代码救赎之路(编译Dll)的更多相关文章
- Snippet Compiler——代码段编译工具
		
原文地址:http://www.cnblogs.com/conexpress/archive/2011/07/24/2115308.html 不知道大家在工作中是否遇到过下面的情况:在项目中实现了一段 ...
 - .NET代码自动编译发布
		
.NET代码自动编译发布 因本人一直使用.NET开发,在做项目的时候,每次都要涉及到各个环境的部署问题,手工操作容易出错,并且重复劳动多,所以一直在寻找一个能实现自动化部署的方案. 废话不多讲,先 ...
 - Android源码树中C代码的编译
		
侯 Sir说:“源码之下,了无秘密.” 但有些秘密还是要搞起来了看得更真切,仅从静态代码的体位很难体会到运动时的妙处.因此环境搭好了,下一步就是调试.gdbserver搭配gdb的调试环境走得很顺利, ...
 - MinGW编译dll并引用
		
记得某位神仙曾经说过:一个项目不使用dll简直是一场灾难.(滑稽) 这篇文章以A+B/A-B为范例,来介绍如何在MinGW下编译dll并引用. 首先你要安装MinGW,并配置好环境变量(不配置环境变量 ...
 - codeforces 1424J,为了过这题,我把祖传的C++都用上了!
		
大家好,我们选择的是Bubble Cup比赛Div2场次的J题,不用问我Bubble Cup是什么比赛,我也不清楚.总之是一场算法比赛就是了.可能是这个比赛知名度比较低吧,参与的人数也不是很多,我们选 ...
 - 上传python代码到pypi
		
上传python代码到pypi 去pypi官网注册账号 在项目中添加setup.py # coding = utf-8 from setuptools import setup, find_packa ...
 - Eclipse下使用GDT插件无法登陆GAE & GDT无法上传JAVA代码
		
今天更新github主页的过程中,想使用GAE部署一个Java Web服务来更好的支持网站动态性(关键是利用了免费的GAE资源),结果遇到了2个大问题. 1.GDT插件无法登陆GAE账户 错误1:登陆 ...
 - git上传项目代码到github
		
参考: git学习——上传项目代码到github github上传时出现error: src refspec master does not match any解决办法 git 上传本地文件到gith ...
 - [html5+java]文件异步读取及上传核心代码
		
html5+java 文件异步读取及上传关键代码段 功能: 1.多文件文件拖拽上传,file input 多文件选择 2.html5 File Api 异步FormData,blob上传,图片显示 3 ...
 
随机推荐
- mall笔记
			
介绍 SpringBoot.SpringCloud.SpringCloudAlibaba.Nacos.Sentinel.Seata整合demo. 软件架构 JDK 1.8 Spring Boot 2. ...
 - JuiceFS 如何帮助趣头条超大规模 HDFS 降负载
			
作者简介 王振华,趣头条大数据总监,趣头条大数据负责人. 王海胜,趣头条大数据工程师,10 年互联网工作经验,曾在 eBay.唯品会等公司从事大数据开发相关工作,有丰富的大数据落地经验. 高昌健,Ju ...
 - Prometheus监控Canal
			
Prometheus监控Canal 一.背景 二.实现步骤 1.修改prometheus.yml配置文件 2.启动prometheus 3.查看prometheus是否成功接入canal 4.cana ...
 - [火星补锅] 非确定性有穷状态决策自动机练习题Vol.1 T3 第K大区间 题解
			
前言: 老火星人了 解析: 很妙的二分题.如果没想到二分答案.. 很容易想到尝试用双指针扫一下,看看能不能统计答案. 首先,tail指针右移时很好处理,因为tail指针右移对区间最大值的影响之可能作用 ...
 - STM32中按键中断分析
			
在按键学习中,我们有用到查询的方法来判断按键事件是否发生,这种查询按键事件适用于程序工作量较少的情况下,一旦程序中工作量较大较多,则势必影响程序运行的效率,为了简化程序中控制的功能模块的执行时间,引入 ...
 - 常用Java API:Calendar日期类
			
摘要 在蓝桥杯中有关于日期计算的问题,正好java中的Date类和Calendar类提供了对日期处理的一些方法.Date类大部分方法已经废弃了,所以本文将详细介绍Calendar类. Calendar ...
 - sed初理多行合并+sed之G、H、g、h使用+sed n/N使用说明
			
转载:[shell]sed处理多行合并 - seyjs - 博客园 (cnblogs.com) 文件格式 table=t1 name owner address table=t2 id text co ...
 - hdu 1160 FatMouse's Speed(最长不下降子序列+输出路径)
			
题意: FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to ...
 - 开发笔记-----Ajax 基础使用
			
一.GET 方式的用法: 1 <!--html --> 2 <div class="layui-form"> 3 <div class="l ...
 - pl/sql 远程连接oracle数据库问题(TNS:丢失连接)
			
前几天还可以连接的,突然就连接失效,别的电脑也连接不上 1.ping 远程数据库的IP,可以ping通. 2.检查服务端的tnsnames.ora文件和本机客户端比较,没问题. 3.查看监听是否启动 ...