前情提要:

编译dll

下面写个最简单的fortran的函数,实现整数加法

! 文件名 add_dll.f95
integer function add2i(x, y)
  integer, intent(in) :: x, y
  add2i = x + y
end function add2i

然后在命令行中用gfortran编译,具体命令为

$ gfortran -c add_dll.f95
$ gfortran -shared -o add_dll.dll add_dll.o

其含义为,第一步通过源代码生成.o文件,第二步通过.o文件,得到add_dll.dll,完成动态链接库的编译。

调用dll

生成动态链接库之后,可先在fortran中小试一下,由于test2i是在外部定义的,所以在类型声明时,需要用到external关键字

! 文件名dll_test.f95
program dll_test
  implicit none
  integer :: a
  integer, external :: add2i
  
  a = add2i(1, 2)
  write (*,*) "1 + 2 = ", a  
end program dll_test

然后在编译的时候别忘了链接刚刚编好的dll,结果如下。

>gfortran -o test dll_test.f95 -L. add_dll.dll
>test.exe
 1 + 2 =            3

数据类型对应

一旦涉及到混合编程,第一步就是统一数据类型,C和fortran的基本类型对应如下表

Fortran 95C大小对齐
BYTEchar11
REALfloat44
INTEGERint44
LOGICALint44
CHARACTER xunsigned char11

在fortran中可通过kind来调整整型或浮点型的位长,而在C中,则通过不同的关键字来表示。其中,

  • 实型real的4位、8位和16位,分别对应C中的float, double, long double
  • 整型integer的1、2、4、8位,分别对应C中的singed char, short, int, long long int
  • 逻辑logical的1、2、4、8位,与integer表现相同。

此外,字符串将被转化为数组,复数则被转换为结构体

Fortran 95C大小对齐
CHARACTER (LEN=n) xunsigned char x[n] ;n1
DOUBLE COMPLEX xstruct {double dr, di;} x;164/8
COMPLEX xstruct {float r,i;} x;84
COMPLEX (KIND=4) xstruct {float r,i;} x;84
COMPLEX (KIND=8) xstruct {double dr,di;} x;164/8
COMPLEX (KIND=16) xstruct {long double dr,di;} x;324/8/16

在C语言中调用

C语言调用动态链接库这个大家都很熟悉了,调用fortran生成的动态链接库也没有什么不同,但有三点需要注意

  1. 别把数据类型搞混,这个在上一节已经给出了对应关系
  2. 需要在fortran函数的后面添加一个下划线,所以add2i在C语言中调用时写为add2i_
  3. 需要将传入变量改为指针的形式
#include<stdio.h>
int add2i_(int*, int*);
int main(){
    int x=1, y=2;
    int a = add2i_(&x, &y);
    printf("1+2=%d", a);
}

然后编译运行

>gcc -o test.exe test.c -L./ -ladd_dll
>test
1+2=3

在这里插入图片描述

更多推荐