在Windows上使用gfortran创建DLL [英] creating DLL with gfortran on Windows
问题描述
我想在Windows上为Fortran项目(实际上是Fortran + C)创建DLL。我遇到麻烦,当一个dll依赖另一个dll时,我在Linux上不见面。
I would like to create DLLs on windows for a Fortran project (in fact Fortran+C). I get a trouble I do not meet on Linux when a dll depends on another one.
这里是一个简短的示例:
Here is a short example :
文件dll1.f90
file dll1.f90
module dll1
implicit none
contains
subroutine test1
write(*,*) "test1 ok"
end subroutine
end module
文件dll2.f90
file dll2.f90
module dll2
use dll1,only : test1
implicit none
contains
subroutine test2
call test1
end subroutine
end module
文件main.f90
File main.f90
program main
use dll2, only : test2
implicit none
call test2
end program
Linux命令(文件run.bash)
Linux commands (file 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)
Windows commands (file 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上,我得到第一个错误消息在第二条指令上:
On Windows, I get the first error message at the second instruction :
对__dll1_MOD_test1的未定义引用(ld消息)
undefined reference to __dll1_MOD_test1 (ld message)
我可以通过修改第二条指令来解决此问题,如下所示:
I can solve this trouble in modifying the second instruction as follows :
gfortran -shared -fPIC -o dll2.dll dll2.f90 -L . -ldll1
但是由于某些原因,这种修改并不方便:
But this modification is not convenient for several reasons :
-
如果一个dll依赖于许多dll,则它的大小将变得很大(它似乎包含所有子dll)
if a dll depends on many dlls, then its size becomes very large (it seems to contain all the sub dlls)
可执行程序的大小也很大
the size of the executable program is large as well
使用经典库而不是dll,我得到的结果要合理得多。 / p>
I get a much more reasonable result using classical libraries instead of dlls
Linux文件大小:
Linux file sizes :
[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文件大小
Windows file sizes
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
所以我的问题是:如何解决这些缺点?
So my question is : how to solve these drawbacks ?
推荐答案
在两种操作系统之间,在符号解析方式方面存在差异用于加载时间动态链接。在Linux中,提供特定符号的库名称的解析可以推迟到加载时,而在Windows中,提供符号的库名称必须在链接时解析。
There is a difference in philosophy between the two operating systems in terms of how symbols are resolved for load time dynamic linking. In linux, the resolution of the name of the library that provides a particular symbol can be deferred till load time, while in Windows the name of the library that will provide a symbol must be resolved at link time.
因此,在Linux下,您可以链接libdll2.so共享库,而无需向链接程序提供有关test1过程目标代码位置的任何信息,而在Windows上链接dll2则需要类似 -ldll1
命令选项。在Windows上链接最终的可执行文件时,则无需重复 -ldll1
规范。
Consequently, under linux you can link the libdll2.so shared library without providing any information to the linker about the location of the object code for the test1 procedure, while linking dll2 on Windows requires something akin to the -ldll1
command option. When linking the final executable on Windows, you then do not need to repeat the -ldll1
specification.
我不能在Windows上使用Msys2 mingw-64 x86_64工具链通过修改后的链接过程重现您的观察结果。
I cannot reproduce your observations with the modified link process on Windows with the Msys2 mingw-64 x86_64 toolchain.
$ 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可执行模块的检查显示了预期的符号导入和导出,并且运行时调试显示执行在
Inspection of the dll and exe executable modules show the expected symbol imports and exports, and runtime debugging shows that execution is being transferred between executable modules.
请注意,剥离调试符号将大大减少EXE和DLL文件的大小。
Note that stripping debugging symbols will spectacularly reduce EXE and DLL file size.
这篇关于在Windows上使用gfortran创建DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!