使用MinGW编译Windows平台下使用的fortran动态链接库

来源:互联网 发布:linux crontab命令 编辑:程序博客网 时间:2024/05/22 14:22

Author:Zengqiang  Date:2013-3-29

      为了能在32位和64位windows平台VS或VC环境下的C/C++工程能够调用fortran语言编写的科学计算库函数或者自己编写的fortran函数,这里采用MinGW软件在windows平台下用unix环境下的GNU make 3.81和相关工具编译出动态链接库。

 

    Step1 下载MinGW32or MinGW64工具并配置

    MinGW软件是一款在Unix/Linux和Windows平台生成本地的Windows程序的开源免费工具集,含有部分Windows特定头文件和GNU工具集,对于Windows和Unix/Linux两个平台下的交叉编译应用提供了极大的方便。

       MinGW提供了32位版本安装包和64位MinGW64-project,以及MSYS工具(32位和64位皆可用),这些软件可以在MinGW官网下载:

           http://www.mingw.org/

       关于MinGW32和MinGW64的安装、配置和使用,请参考下文中的第一部分,有详细的步骤说明:

           http://blog.csdn.net/guillotine007/article/details/8636647

        到此为止,我们认为您已经正确安装和配置好了MinGW32或MinGW64,接下来切入正题。


    Step2编写您的Makefile并编译出object文件

      这里用实例来说明,代码可以参考使用。

      我有一系列fortran源文件实现了特征值和特征向量的求解,这些文件如图所示,我把它们放在了一个名为dsdrvlib的文件夹下:


      Debug.h和stat.h里面是部分变量的声明,与外部的调用接口函数定义在dsdrv3.f中。现在要编译出所有f源文件的目标文件。

      Makefile文件内容如下:

ARPACKLIB = dsdrv.a

 

.SUFFIXES:

.SUFFIXES:  .f  .o

 

FC = gfortran

FFLAGS =

AR = ar

ARFLAGS = rv

RANLIB = ranlib

 

DOBJ  = daxpy.o dcopy.o ddot.o dgemv.o dgeqr2.o dger.o dgetv0.o dgttrf.o \

    dgttrs.o dlacpy.o dlae2.o dlaev2.o dlamch.o dlanst.o dlapy2.o dlarf.o\

    dlarfg.o dlarnv.o dlartg.o dlaruv.o dlascl.o dlaset.o dlasr.o dlasrt.o\

    dlassq.o dmout.o dnrm2.o dorm2r.o dsaitr.o dsapps.o dsaup2.o dsaupd.o\

    dscal.o dsconv.o dsdrv3.o dseigt.o dsesrt.o dseupd.o dsgets.o dsortr.o\

    dstats.o dsteqr.o dstqrb.o dswap.o dvout.o ivout.o lsame.o second.o\

    xerbla.o

 

.f.o:

    $(FC) $(FFLAGS) -c $<

 

all: double

 

double: $(DOBJ)

    $(AR) $(ARFLAGS) $(ARPACKLIB) $(DOBJ)

    $(RANLIB) $(ARPACKLIB)

 

help:

    @$(ECHO) "usage:make ?"

 

.PHONY:clean

clean:

       rm -f *.o a.out core

      使用了make的隐含规则,这里没有给出.h文件的依赖,它会自动找到.h文件的依赖。

      这里使用的是make 3.81版本,也是目前应用最广泛的版本,新版的GNU-GCC工具集中用gfortran代替了以前的f77工具,所以这里的FC变量设成了gfortran,各位如果有类似的实例,只需要替换Makefile中的DOBJ里的.o文件即可修改成适合自己的Makefile,启动msys.bat,再进入dsdrvlib目录:

      此时已经准备好了Makefile文件,输入make命令等待编译完成并查看结果:

      除了多了所有.f文件对应的.o文件,还有一个dsdrv.a文件,该文件是所有.o文件的一个打包文件,也称为静态库,在Unix/Linux下为.a文件,在windows下为.lib文件,该文件在Unix/Linux系统下可以被C/C++直接链接了,但是在windows系统下,由于一些调用约定对函数名称的wrap修饰,会导致直接链接找不到对应的函数。

      OK,一步一步来,现在已经得到了所有的object文件了。

 

      Step3使用MinGW32/64来得到Windows下使用的库

      仍然使用msys工具进入dsdrvlib文件夹中,使用dllwrap工具生成dll和def文件,dll文件中是所有object文件的集合,是代码的二进制实现,def文件包含了dll文件中的函数名称和在dll文件中的入口地址,dllwrap命令使用如下:

            dllwrap --export-all-symbols *.o -lgfortran --output-def dsdrv32.def -o dsdrv32.dll

      其中dsdrv32.def和dsdrv32.dll是我自己定义的输出文件名。

      如果你使用的是MinGW64中的相关工具集,那么以上的步骤完全相同,产生出来的文件是专门用于64位windows应用的,64位下可以把名称修改为dsdrv64.def和dsdrv64.dll来区分。

            dllwrap--export-all-symbols *.o -lgfortran --output-def dsdrv64.def -o dsdrv64.dll

      msys在执行完该命令后:


      查看文件夹,发现多了2个文件,一个是dsdrv32.def,一个是dsdrv32.dll文件。此时如果你在Windows下想使用显式链接的方式使用动态链接库,那么在你的C/C++工程中调用Windows的API:

HINSTANCE hDLL;                   //Handle to DLL
hDLL = LoadLibrary("MyDLL");   //Load DLL
FreeLibrary(hDLL);                  //Free DLL
此时只需要将dll文件拷贝到你的工程中使用即可咯!
如果你想使用隐式链接的方式加载DLL,那么请继续往下看咯!
隐式链接的方式是指不适用Windows的API来加载dll,而是在源文件中使用e
xtern调用的形式来加载dll:
#ifdef __cplusplus
extern "C" {
#endif
void dsdrv3_(int *row, int *col, double *vv, double *dvalue, double *a_mat, double *b_mat, double *binv_mat);     
#ifdef __cplusplus
}
#endif

      当然,如果源文件是c文件就只需要:

extern "C" void dsdrv3_( int *row, int *col, double *vv, double *dvalue, double *a_mat, double *b_ mat, double *binv_mat);

      用这种隐式链接的方式加载dll,就需要lib文件了,lib文件可以用微软VS/VC平台中自带的lib.exe工具生成,前提是需要dll对应的def文件,前面我们已经得到了dsdrv64.def文件。

      lib.exe的路径:

            D:\MySoftWares\Microsoft VisualC++\VC98\Bin\LIB.EXE

      找到你的VC安装路径替换即可找到lib.exe了。

      如果你使用的是Visual Studio,在相应路径下也可找到,例如:

            C:\Program Files(x86)\Microsoft Visual Studio 8\VC\bin\lib.exe

      找到lib.exe后,将其路径加入环境变量,当然一般VS/VC安装时该目录已经加入环境变量了。

      在msys.bat中进入dsdrvlib目录,输入命令:

            lib /machine:X86 /def:dsdrv32.def

      这里得到的是32位下的lib,如果你想使用64位下的lib,一定要使用VS平台下64位的lib工具,输入命令:

            lib /machine:X64 /def:dsdrv64.def

      在运行命令前,请确保你已经得到了响应的def文件。

      来看看目录里的结果:


      可以看到,目录中多了一个文件dsdrv32.lib,你就可以把lib和dll文件拷贝到你的C/C++工程中使用了,64位下的方法步骤是一样的,只是用的工具都是64位下对应的工具!

      OK,希望能帮助到各位,文中有不当之处尽请指正!

Zeng qiang

2013-03-30




原创粉丝点击