kkkttt 发表于 2015-10-27 07:56

基于动态链接库DLL实现FOTRAN与VC++混合编程

编译环境:
Windows 7、Visual Studio 2008 Professional 、Intel Visual Fotran Compiler Professional V11.1.060

方法一:把FORTRAN子程序做成动态链接库供VC++主程序显式调用。

在此方法中,应用程序在运行时通过函数调用来显示装载和卸载DLL,并通过函数指针来调用DLL的导出函数。使用显示链接的基本方式:调用LoadLibrary或AfexLoadLibrary装载DLL并得到模块句柄;调用GetProcAddress来获得导出函数的指针;在使用完毕时,调用FreeLibrary或AfxFreeLibrary函数释放DLL。

(1)创建FORTRAN DLL工程(工程名:Fsubroutines;添加源文件:Fsubroutines.f90),生成 Fsubroutines.dll 文件供调用。
!Fsubroutines.f90
!FUNCTIONS/SUBROUTINES exported fromFsubroutines.dll
!Fsubroutines      - subroutine
!
INTEGER*4 FUNCTION Fact (n)
   !DEC$ ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_FACT@4'::Fact
      INTEGER*4 n
      INTEGER*4 i, amt
      amt = 1
      DO i = 1, n
      amt = amt * i
      END DO
      Fact = amt
   write(*,*)"Mixed calls succeed!"
END FUNCTION Fact

SUBROUTINE Pythagoras (a, b, c)
   !DEC$ ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_PYTHAGORAS@12'::Pythagoras
      REAL*4 a
      REAL*4 b
      REAL*4 c
      c = SQRT (a * a + b * b)
END SUBROUTINE Pythagoras

(2)创建win32 console application(工程名:CFotran;添加源文件:CFortran.cpp),调用 Fsubroutines.dll。

//CFortran.cpp
//C++显式调用FORTRAN动态链接库
#include <stdio.h>
#include <iostream>
#include <windows.h>

using namespace std;

//extern "C" {int _stdcall FACT (int n);}
//extern "C" {void _stdcallPYTHAGORAS (float a, float b, float *c);}

int main()
{
//声明调用约定
typedef int (_stdcall * FACT)(int n);
typedef void (_stdcall * PYTHAGORAS)(float a, float b, float *c);
//此处紫色部分应与FORTRAN源文件中紫色部分一致
//加载动态库文件
HINSTANCE hLibrary=LoadLibrary("D:\\dll\\Fsubroutines.dll");
//由于FORTRAN编译后生成的.dll文件路径太深,故将生成的 Fsubroutines.dll 复制到 D:\dll 目录中
if(hLibrary==NULL)
{
cout<<"can't find the dll file (Fsubroutines.dll)"<<endl;
return -1;
}


//获得Fortran导出函数FACT的地址
FACT fact=(FACT)GetProcAddress(hLibrary,"_FACT@4");
//注意此处红色部分应与FORTRAN源文件红色部分相同
if(fact==NULL)
{
cout<<"can't find the function file (FACT)."<<endl;
return -2;
}

//获得Fortran导出函数PYTHAGORAS的地址
PYTHAGORAS pythagoras=(PYTHAGORAS)GetProcAddress(hLibrary,"_PYTHAGORAS@12");
//注意此处蓝色部分应与FORTRAN源文件蓝色部分相同
if(pythagoras==NULL)
{
cout<<"can't find the function file (PYTHAGORAS)."<<endl;
return -2;
}
    float c;
    printf("Factorial of 7 is: %d\n", fact(7));
    pythagoras (30, 40, &c);
    printf("Hypotenuse if sides 30, 40 is: %f\n", c);
FreeLibrary(hLibrary); //卸载动态库文件
getchar();
return 0;

}


方法二:把FORTRAN子程序做成库文件供VC++主程序隐式调用。

在此方法中,使用DLL的应用程序链接到编译DLL是通过生成的导入库lib文件,在执行这个程序时,系统也需要装载其他所需要的DLL。在程序退出之前,DLL一直存在于该程序进程的地址空间,占据内存。

(1) 创建FORTRAN DLL工程(工程名:Fsubroutines;添加源文件:Fsubroutines.f90),生成 Fsubroutines.dll和 Fsubroutines.lib文件供调用。
!Fsubroutines.f90
!
!FUNCTIONS/SUBROUTINES exported from Fsubroutines.lib:
!Fsubroutines      - subroutine
!
INTEGER*4 FUNCTION Fact (n)
!ms$if .not. defined(LINKDIRECT)
!ms$attributes dllexport,stdcall,alias:'_Fact@4'::Fact
!ms$endif
      INTEGER*4 n
      INTEGER*4 i, amt
      amt = 1
      DO i = 1, n
      amt = amt * i
      END DO
      Fact = amt
   write(*,*)"Mixed calls succeed!"
END FUNCTION Fact

SUBROUTINE Pythagoras (a, b, c)
!ms$if .not. defined(LINKDIRECT)
!ms$attributes dllexport,stdcall,alias:'_Pythagoras@12'::Pythagoras
!ms$endif      
   REAL*4 a
      REAL*4 b
      REAL*4 c
      c = SQRT (a * a + b * b)
END SUBROUTINE Pythagoras

(2)创建win32 console application(工程名:CFotran;添加源文件:CFortran.cpp),添加 Fsubroutines.lib到工程,动态调用 Fsubroutines.dll。
注:将上一步生成的 Fsubroutines.dll和 Fsubroutines.lib 复制到 CFortran.cpp所在的目录
//CFortran.cpp
#include <stdio.h>
#include <iostream>

extern "C" {int _stdcall Fact (int n);}
extern "C" {void _stdcallPythagoras (float a, float b, float *c);}

int main()
{
    float c;
    printf("Factorial of 7 is: %d\n", Fact(7));
    Pythagoras(30, 40, &c);
    printf("Hypotenuse if sides 30, 40 is: %f\n", c);
}
页: [1]
查看完整版本: 基于动态链接库DLL实现FOTRAN与VC++混合编程