2

我正在通过 Microsoft Visual Studio 2015 IDE 使用 Intel Fortran Compiler 15.0。我正在学习 OpenMP 以(最终)并行运行我的代码部分。我的代码需要从 .dll 加载子例程。我有以下程序加载带有 HelloWorld 子例程的 .dll 并调用该子例程;下面的代码在一个简单的控制台应用程序中执行得很好。

program LoadThisLibrary
 
Use DFWIN
Use DFLIB

implicit none

!Variable declarations
Character (len=8) SubName

!Pointer declarations
 Integer i !not used but must be declared as part of a POINTER declaration.
 Pointer (p,i)
 Integer(INT_PTR_KIND()) paa(100)  !declares an integer array that will contain pointer addresses
 
!Declare an interface for MySub                                            
 Interface
   Subroutine MySub
   End Subroutine MySub
 End Interface
 
! Declare a pointer/pointee structure - this allows us to later "call" a pointer by its pointee (subroutine) name. 
! This is a CVF function, not "pure fortran"  
 Pointer(SubNum,MySub) 
 
!Load the dll that contains the subroutine we want to run
p = LoadLibrary("HelloDLL.dll"C) 
 
!Name the subroutine we wish to call from that dll
SubName = TRIM("HELLOSUB")//CHAR(0)

!Get a pointer to the subroutine we want and store it in the pointer array
paa(1) = GetProcAddress(p,SubName)

!set a POINTER to the subroutine's memory location
SubNum = paa(1) 

!Call the subroutine loaded from the dll
 Call MySub

end

这是“HelloDLL.dll”的代码

subroutine HelloSub

  ! Expose subroutine HelloSub to users of this DLL
  !
  !DEC$ATTRIBUTES DLLEXPORT :: HelloSub

  ! Variables
  character variable
  
  ! Body of HelloSub 
  print *, "Congratulations! You have run a dll subroutine. You are the best. I am in awe of your brilliance. You have triumphed in the face of adversity. "
  READ(*,*) variable

end subroutine HelloSub

为了启用 OpenMP 指令,我转到项目 -> 控制台属性(在我的 IDE 中),然后是 Fortran -> 语言,并将“处理 OpenMP 指令”设置为“生成并行代码 (/Qopenmp)”。当我这样做时,没有其他任何事情,对我的源代码进行任何更改,我的代码将不再运行。具体来说,我发现 LoadLibrary 仍然找到 HelloDLL.dll 的地址,但 GetProcAddress 调用返回一个空值 (0)。在主程序代码中是否包含 USE OMP_LIB 或使用任何 OpenMP 指令或函数似乎并不重要。我尝试重命名 paa() 数组,甚至将地址保存为纯整数 - 似乎没有任何效果。

如果您有任何建议或见解,我将不胜感激。显然,启用 OpenMP 不仅仅是允许访问 OpenMP 的功能,我只是无法弄清楚为什么它会对 GetProcAddress 产生任何影响。如果可以的话请帮忙!提前谢谢了。

4

1 回答 1

1

以空结尾的子例程名称 (8+1 = 9) 长于SubName变量 (8) 的长度。虽然分配给 的表达式中存在空终止符SubName,但它将作为分配的一部分被切掉(您不能将 9 个字符放入 8 个字符中)。

空终止符是否恰好紧跟在存储之后SubName取决于内存中变量的布局(以及可能的随机机会)。如果没有空终止符,传递给 GetProcAddress 的名称将是无意义的。内存中变量的布局/Qopenmp会发生变化。

修正 的长度SubName。考虑使用可分配的字符标量,以使您的代码对以后更改过程名称的长度具有鲁棒性。

(存在其他样式或可移植性问题,但它们更主观。)

于 2020-07-28T23:12:36.173 回答