Export COMMON block from DLL with gfortran

旧巷老猫 提交于 2019-12-11 11:34:13

问题


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.

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

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

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

 Before           0           0
 After           1           2

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.

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

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

or

!GCC$ ATTRIBUTES DLLEXPORT :: numbers

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


回答1:


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:

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));


Second, only the line

!GCC$ ATTRIBUTES DLLIMPORT :: a, b

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.)



来源:https://stackoverflow.com/questions/57617560/export-common-block-from-dll-with-gfortran

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!