【问题标题】:creating DLL with gfortran on Windows在 Windows 上使用 gfortran 创建 DLL
【发布时间】:2017-12-29 11:34:46
【问题描述】:

我想在 Windows 上为 Fortran 项目(实际上是 Fortran+C)创建 DLL。当一个 dll 依赖于另一个 dll 时,我遇到了在 Linux 上没有遇到的问题。

这是一个简短的例子:

文件 dll1.f90

module dll1
   implicit none
   contains
   subroutine test1
      write(*,*) "test1 ok"
   end subroutine
end module

文件 dll2.f90

module dll2
   use dll1,only : test1
   implicit none
   contains
   subroutine test2
      call test1
   end subroutine
end module

文件 main.f90

program main
   use dll2, only : test2
   implicit none
   call test2
end program

Linux 命令(文件 run.bash)

gfortran -shared -fPIC -o libdll1.so dll1.f90
gfortran -shared -fPIC -o libdll2.so dll2.f90
gfortran -o main.exe main.f90 -I. -L. -ldll2 -ldll1
export LD_LIBRARY_PATH="./"
./main.exe

Windows 命令(文件 run.bat)

gfortran -shared -fPIC -o dll1.dll dll1.f90
gfortran -shared -fPIC -o dll2.dll dll2.f90
gfortran -o main.exe main.f90 -I. -L. -ldll2 -ldll1
.\main.exe

在 Windows 上,我在第二条指令处收到第一条错误消息:

对 __dll1_MOD_test1 的未定义引用(ld 消息)

我可以通过修改第二条指令来解决这个问题:

gfortran -shared -fPIC -o dll2.dll dll2.f90 -L . -ldll1

但是这个修改不方便有几个原因:

  • 如果一个dll依赖很多dll,那么它的大小就会变得非常大(似乎包含了所有的子dll)

  • 可执行程序也很大

  • 我使用经典库而不是 dll 得到了更合理的结果

Linux 文件大小:

[coul@localhost dll]$ ls -al
total 68
drwxrwxr-x  2 coul coul 4096 29 déc.  12:09 .
drwxrwxr-x. 7 coul coul 4096 29 déc.  11:46 ..
-rw-rw-r--  1 coul coul  118 29 déc.  11:25 dll1.f90
-rw-rw-r--  1 coul coul  204 29 déc.  12:09 dll1.mod
-rw-rw-r--  1 coul coul  132 29 déc.  11:29 dll2.f90
-rw-rw-r--  1 coul coul  237 29 déc.  12:09 dll2.mod
-rwxrwxr-x  1 coul coul 8184 29 déc.  12:09 libdll1.so
-rwxrwxr-x  1 coul coul 7920 29 déc.  12:09 libdll2.so
-rwxrwxr-x  1 coul coul 8712 29 déc.  12:09 main.exe
-rw-rw-r--  1 coul coul   82 29 déc.  11:27 main.f90
-rwxrwxr-x  1 coul coul  183 29 déc.  11:38 run.bash
-rw-rw-r--  1 coul coul  151 29 déc.  11:55 run.bat

Windows 文件大小

29/12/2017  11:53    <DIR>          .
29/12/2017  11:53    <DIR>          ..
29/12/2017  11:53         2 264 764 dll1.dll
29/12/2017  11:25               118 dll1.f90
29/12/2017  11:50               204 dll1.mod
29/12/2017  11:53            51 814 dll2.dll
29/12/2017  11:29               132 dll2.f90
29/12/2017  11:50               237 dll2.mod
29/12/2017  11:53         2 264 671 main.exe
29/12/2017  11:27                82 main.f90
29/12/2017  11:38               183 run.bash
29/12/2017  11:53               162 run.bat

所以我的问题是:如何解决这些缺点?

【问题讨论】:

    标签: windows dll fortran


    【解决方案1】:

    在加载时动态链接的符号解析方式方面,两种操作系统的理念有所不同。在 linux 中,提供特定符号的库名称的解析可以推迟到加载时,而在 Windows 中,提供符号的库名称必须在链接时解析。

    因此,在 linux 下,您可以链接 libdll2.so 共享库,而无需向链接器提供有关 test1 过程的目标代码位置的任何信息,而在 Windows 上链接 dll2 需要类似于 -ldll1 命令选项的东西.在 Windows 上链接最终可执行文件时,您无需重复 -ldll1 规范。

    我无法在 Windows 上使用 Msys2 mingw-64 x86_64 工具链修改链接过程来重现您的观察结果。

    $ gfortran -shared -fPIC -o dll1.dll dll1.f90
    $ gfortran -shared -fPIC -o dll2.dll dll2.f90 -L. -ldll1
    $ gfortran -o main main.f90 -L. -ldll2
    $ ./main.exe
     test1 ok
    
    $ du -b *
    330013  dll1.dll
    125     dll1.f90
    204     dll1.mod
    329573  dll2.dll
    140     dll2.f90
    237     dll2.mod
    398054  main.exe
    87      main.f90
    

    对 dll 和 exe 可执行模块的检查显示了预期的符号导入和导出,运行时调试显示执行正在可执行模块之间传输。

    请注意,去除调试符号会显着减小 EXE 和 DLL 文件的大小。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 2012-01-26
    • 1970-01-01
    相关资源
    最近更新 更多