Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用gfortran从DLL导出公共块_Dll_Fortran_Gfortran_Mingw W64 - Fatal编程技术网

使用gfortran从DLL导出公共块

使用gfortran从DLL导出公共块,dll,fortran,gfortran,mingw-w64,Dll,Fortran,Gfortran,Mingw W64,当变量是公共块的一部分时,我无法从Fortran EXE正确访问Fortran DLL中的变量 我有一个简单的代码simple.f90,我使用MSYS64/MinGW-w64 gfortran 9.2作为 x86_64-w64-mingw32-gfortran simple.f90 -o simple.dll -shared 该库来自一个更简单的程序prog.f90,编译如下 x86_64-w64-mingw32-gfortran prog.f90 -o prog -L. -lsimple

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

我有一个简单的代码simple.f90,我使用MSYS64/MinGW-w64 gfortran 9.2作为

x86_64-w64-mingw32-gfortran simple.f90 -o simple.dll -shared
该库来自一个更简单的程序prog.f90,编译如下

x86_64-w64-mingw32-gfortran prog.f90 -o prog -L. -lsimple
当注释掉
公共
/numbers/
时,代码工作并打印预期结果:

 Before           0           0
 After           1           2
但是,当我取消注释
COMMON
块时,输出变为

 Before           0           0
 After           0           0
好像程序使用的变量突然与库中使用的变量不同

这两种变体在使用gfortran 9.1的基于Linux的操作系统中同样有效

我知道“在某些系统上,过程和全局变量(模块变量和公共块)需要特殊处理,以便在共享库中访问”,如下所述:。但是,我无法插入该类型的语句

!GCC$ ATTRIBUTES DLLIMPORT :: numbers


在代码中的任何位置都不会被编译器捕捉。

正如M.Chinoune在文章中指出的那样,当前的gfortran缺乏从DLL导入公共块的能力。尽管已经有一段时间了,但它尚未合并。最后,我需要两件事才能使上述代码正常工作:

首先,将以下修补程序应用于GCC 9.2,并在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));



在主程序中需要(就在
implicit none
之后),但在任何地方都不需要任何导出。这显然是一种不同于英特尔Fortran的语法方法,在英特尔Fortran中,导入的是
公共
块,而不是其组成部分。我还发现我需要导入
a
b
,即使我只需要
b
。(当只需要
a
时,只导入
a
就足够了。)

正如M.Chinoune在中指出的那样,当前的gfortran缺乏从DLL导入公共块的能力。尽管已经有一段时间了,但它尚未合并。最后,我需要两件事才能使上述代码正常工作:

首先,将以下修补程序应用于GCC 9.2,并在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));



在主程序中需要(就在
implicit none
之后),但在任何地方都不需要任何导出。这显然是一种不同于英特尔Fortran的语法方法,在英特尔Fortran中,导入的是
公共
块,而不是其组成部分。我还发现我需要导入
a
b
,即使我只需要
b
。(当只需要
a
时,只导入
a
就足够了。)

尝试在属性指令中使用
/numbers/
。ifort就是这样做的。代码是无效的Fortran,所以gfortran可以做它想做的任何事情。@SteveLionel谢谢你的建议,但当我用斜杠括起
数字时,gfortran吐出了“错误:名称中的无效字符”@您能否更具体地说明代码的哪些部分无效以及如何修复它?当您尝试使用
print*,“Before”,a,b
打印它们时,您希望
a
b
具有什么值<代码>a
b
未定义!如果您使用的是模块,则不要使用
common
。这是gfortran中的已知错误,请尝试在属性指令中使用
/numbers/
。ifort就是这样做的。代码是无效的Fortran,所以gfortran可以做它想做的任何事情。@SteveLionel谢谢你的建议,但当我用斜杠括起
数字时,gfortran吐出了“错误:名称中的无效字符”@您能否更具体地说明代码的哪些部分无效以及如何修复它?当您尝试使用
print*,“Before”,a,b
打印它们时,您希望
a
b
具有什么值<代码>a
b
未定义!如果您使用的是模块,则不要使用
common
。这是gfortran中已知的错误
!GCC$ ATTRIBUTES DLLEXPORT :: numbers
--- 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