回 帖 发 新 帖 刷新版面

主题:程序编译后的移植性问题

为了给FORTRAN程序打包,我用Intel Visual Fortran 11.1编译器在windows系统中进行编译,编译过程都正确。并在编译程序的文件夹下测试编译的执行文件成功。但是把执行文件和所依赖的DLL拷贝到同一机器的另一个文件夹里的时候,执行程序却不能运行了,并报错:
      “无法启动此程序,因为计算机中丢失MSVCR90.DLL。尝试重新安装该程序以解决问题。”
请问我该怎么将编译好的执行文件移植到别的文件夹中,或者其它机器上呢?

下附我的代码和程序编译过程:
**** modll.f90 ****
      module global
        implicit real(kind(1.d0)) (a-h,o-z)
        !DEC$ ATTRIBUTES DLLEXPORT :: x, n
        allocatable :: x(:)
        integer :: n
      end module global
------------------------------------------------------
**** testdll.f90 ****
      subroutine tsum(ave)
      use global
      !DEC$ ATTRIBUTES DLLEXPORT :: tsum
      real*8 :: ave
      write(*,"('dll: the array is: ',/,i4,/,10(5x,5f10.4))") n,(x(i),i=1,n)
      ave = 0
      do i = 1, n
        ave = ave + x(i)
      enddo
      ave = ave / real(n)
      return
      end subroutine tsum
------------------------------------------------------
**** test.f90 ****
      program test
      use global
!
      real*8 ave
      n = 5
      allocate(x(n))
      do i = 1, n
        x(i) = 10.d0*sin(3.14/real(i))
      enddo
      write(*,"('the array x is: ',/,10(5x,5f10.4,/))") x
      call tsum(ave)
      write(*,"('the average is: ',/,5x,f10.4)") ave
      end
------------------------------------------------------
程序的命令行编译命令是:
ifort /dll modll.f90
ifort /dll testdll.f90 modll.lib
ifort /MD test.f90 testdll.lib modll.lib

回复列表 (共6个回复)

沙发

fortran弄dll的我不懂, 没弄过. 
是不是windows下dll是需要注册的

板凳

修改你的编译选项,将使用动态库改为使用静态库。
否则需要用Depend或是其他软件找出对应的DLL并且除系统DLL外都需要随着:)

3 楼

多谢您建议哈。
那么我在命令添加什么参数才能让ifort去链接静态链接库呢?

4 楼

在VS安装后文件夹下找到MSVCR90.DLL,拷贝到SYSTEM32文件夹
这个是你上次在CVF下的代码:
!dll.f90
module global
        implicit real(kind(1.d0)) (a-h,o-z)    
        !DEC$ ATTRIBUTES DLLEXPORT :: X
        !DEC$ ATTRIBUTES DLLEXPORT :: N    
        allocatable :: x(:)
        integer :: n
contains
    subroutine print_test
    !DEC$ ATTRIBUTES DLLEXPORT :: print_test
        write(*,*) "hello world!"
    end subroutine 
end module global

!test.f90
    program test
      use global
      n = 5
      allocate(x(n))
      do i = 1, n
        x(i) = 10.d0*sin(3.14/real(i))
      enddo
      write(*,"('the array x is: ',/,10(5x,5f10.4,/))") (x(i),i=1,n)
     call print_test
      end

下面是测试结果:
E:\test\dll_test>ifort /dll dll.f90
Intel(R) Visual Fortran Compiler Professional for applications running on IA-32,
 Version 11.1    Build 20100203 Package ID: w_cprof_p_11.1.060
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.
-out:dll.dll
-dll
-implib:dll.lib
dll.obj
   Creating library dll.lib and object dll.exp

E:\test\dll_test>ifort test.f90 dll.lib

-out:test.exe
-subsystem:console
test.obj
dll.lib

E:\test\dll_test>test
the array x is:
         0.0159   10.0000    8.6576    7.0683    5.8753

 hello world!

5 楼

现在我知道问题出在那里了。
这问题都是Windows 的Assembly Manifest搞的鬼。这个东东的作用就是为了解决 以前windows上的“Dll 地狱” 问题才产生的新的DLL管理解决方案。详细原因参考[url=http://hi.baidu.com/codinglife/blog/item/ea9acceab2f833d7d539c90e.html]“Assembly Manifest 通俗简易手册”[/url]。
在我用IVF11.1编译完代码后,在文件夹里会对应的生成以下三个文件:
test.exe.manifest
modll.dll.manifest
testdll.dll.manifest
于是我照参考博文里的方法,附带着这三个文件和编译生成的可执行文件和DLL,拷贝到同一机器下的不同目录里测试程序。结果依然会报错,测试不通过。:(
带着失望,我又是好一阵折腾,结果总算是解决问题了:其实跟上面的方法只有一个小差别,就是不能只把文件拷贝到其它文件夹中,而是要把包含编译这些文件所在文件夹一并拷贝到别的文件夹或者别的机器。之后,程序测试就一切正常了。
我怀疑可能与文件夹名有关,于是修改文件夹名后再测试,一切正常。
然后我又确认了,文件夹不包含其它的隐藏没显示的文件。
……
问题完美解决,可是为什么一定要带着文件夹呢?真是莫明奇妙啊~

6 楼

按你的方法测试了一遍,总算是搞明白之前怎么会不能运行了。
因为我之前只是把MSVCRT90.DLL拷到system32里了,而没有重新编译代码。
多谢咯:)

我来回复

您尚未登录,请登录后再回复。点此登录或注册