使用gfortran从DLL导出COMMON块 [英] Export COMMON block from DLL with gfortran

查看:112
本文介绍了使用gfortran从DLL导出COMMON块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当变量是COMMON块的一部分时,我无法从Fortran EXE正确访问Fortran DLL中的变量.

I am having trouble correctly accessing a variable in a Fortran DLL from a Fortran EXE when the variable is part of a COMMON block.

我有一个简单的代码 simple.f90 ,我使用MSYS64/MinGW-w64 gfortran 9.2将其编译为DLL

I have a trivial code simple.f90 which I compile into a DLL using MSYS64/MinGW-w64 gfortran 9.2 as

x86_64-w64-mingw32-gfortran simple.f90 -o simple.dll -shared

! simple.f90

module m
    implicit none
    integer :: a, b
   !common /numbers/ a, b
end module

subroutine init_vals
    use m
    implicit none
    a = 1
    b = 2
end subroutine

该库用于甚至更简单的程序 prog.f90 ,编译为

This library is used from a even simpler program prog.f90, compiled as

x86_64-w64-mingw32-gfortran prog.f90 -o prog -L. -lsimple

! prog.90

program p

    use m
    implicit none

    print *, 'Before', a, b
    call init_vals
    print *, 'After', a, b

end program

COMMON/numbers/被注释掉时,代码开始工作并打印预期结果:

When the COMMON block /numbers/ is commented out, the code works and prints the expected result:

 Before           0           0
 After           1           2

但是,当我取消注释COMMON块时,输出变为

However, when I uncomment the COMMON block, the output becomes

 Before           0           0
 After           0           0

好像程序使用的变量突然不同于库中使用的变量.

as if the variables used by the program were suddenly distinct from those used in the library.

两个变体在具有gfortran 9.1的基于Linux的操作系统中均能很好地工作.

Both variants work equally well in a Linux-based OS with gfortran 9.1.

我知道在某些系统上,过程和全局变量(模块变量和COMMON块)在共享库中时需要进行特殊处理才能访问",如下所述:

I am aware that "On some systems, procedures and global variables (module variables and COMMON blocks) need special handling to be accessible when they are in a shared library," as mentioned here: https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gfortran/GNU-Fortran-Compiler-Directives.html . However, I was not able to insert a statement of the type

!GCC$ ATTRIBUTES DLLIMPORT :: numbers

!GCC$ ATTRIBUTES DLLEXPORT :: numbers

在代码中的任何位置,而不会被编译器锁定.

anywhere in the code without being snapped at by the compiler.

推荐答案

正如M. Chinoune在补丁了,但这并不是尚未合并.最后,我需要做两件事才能使上面的代码起作用:

As pointed out by M. Chinoune in the comment, current gfortran lacks the ability to import common blocks from DLLs. Even though there has been a patch for some time, it is not yet merged. In the end, I needed two things to make the above code work:

首先,将以下修补程序应用于GCC 9.2,然后在MSYS2中手动编译该编译器:

First, apply the following patch to GCC 9.2 and compile the compiler manually in MSYS2:

--- gcc/fortran/trans-common.c.org  2019-03-11 14:58:44.000000000 +0100
+++ gcc/fortran/trans-common.c      2019-09-26 08:31:16.243405900 +0200
@@ -102,6 +102,7 @@
 #include "trans.h"
 #include "stringpool.h"
 #include "fold-const.h"
+#include "attribs.h"
 #include "stor-layout.h"
 #include "varasm.h"
 #include "trans-types.h"
@@ -423,6 +424,9 @@
   /* If there is no backend_decl for the common block, build it.  */
   if (decl == NULL_TREE)
     {
+      unsigned id;
+      tree attribute, attributes;
+
       if (com->is_bind_c == 1 && com->binding_label)
        decl = build_decl (input_location, VAR_DECL, identifier, union_type);
       else
@@ -454,6 +458,23 @@

       gfc_set_decl_location (decl, &com->where);

+      /* Add extension attributes to COMMON block declaration. */
+      if (com->head)
+       {
+         attributes = NULL_TREE;
+         for (id = 0; id < EXT_ATTR_NUM; id++)
+           {
+             if (com->head->attr.ext_attr & (1 << id))
+               {
+                 attribute = build_tree_list (
+                   get_identifier (ext_attr_list[id].middle_end_name),
+                   NULL_TREE);
+                 attributes = chainon (attributes, attribute);
+               }
+           }
+         decl_attributes (&decl, attributes, 0);
+       }
+
       if (com->threadprivate)
        set_decl_tls_model (decl, decl_default_tls_model (decl));


第二,只有一行

!GCC$ ATTRIBUTES DLLIMPORT :: a, b

在主程序中(在implicit none之后)需要

,但在任何地方都没有任何导出.这显然是与Intel Fortran不同的语法方法,在Intel Fortran中,此方法导入COMMON块而不是其组成部分.我还发现,即使我只需要b,也需要同时导入ab. (当只需要a时,仅导入a就足够了.)

was needed in the main program (right after implicit none), but not any exports anywhere. This is apparently a different syntactical approach then in Intel Fortran, where one imports the COMMON block rather than its constituents. I also found out that I needed to import both a and b even if I only needed b. (When only a was needed, importing a only was enough.)

这篇关于使用gfortran从DLL导出COMMON块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆