提问人:A_Weiss 提问时间:7/29/2020 更新时间:7/29/2020 访问量:223
将 OpenMP 和 Intel Visual Fortran 与 Windows GetProcAddress 结合使用
Using OpenMP and Intel Visual Fortran with Windows GetProcAddress
问:
我正在通过 Microsoft Visual Studio 2015 IDE 使用英特尔 Fortran 编译器 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 指令,我转到 Project -> Console Properties(在我的 IDE 中),然后转到 Fortran -> Language,并将 “Process OpenMP Directives” 设置为 “Generate Parallel Code (/Qopenmp)”。当我这样做时,没有别的,不对我的源代码进行任何更改,我的代码不再运行。具体来说,我发现 LoadLibrary 仍然可以找到 HelloDLL.dll 的地址,但 GetProcAddress 调用返回一个 null 值 (0)。我是否在主程序代码中包含 USE OMP_LIB或使用任何 OpenMP 指令或函数似乎并不重要。我尝试重命名 paa() 数组,甚至将地址保存为一个普通整数 - 似乎没有任何效果。
我将不胜感激任何建议或见解。显然,启用 OpenMP 不仅仅是允许访问 OpenMP 的功能,我只是无法弄清楚为什么它会对 GetProcAddress 产生任何影响。如果可以的话,请帮忙!提前非常感谢。
答:
以 null 结尾的子例程名称 (8+1 = 9) 比变量 (8) 的长度长。当表达式 assigning to 中存在 null 终止符时,它将作为赋值的一部分被截断(不能将 9 个字符放入 8 个字符中)。SubName
SubName
null 终止符是否恰好紧跟在存储 for 之后取决于内存中变量的布局(以及可能的随机机会)。如果没有 null 终止符,传递给 GetProcAddress 的名称将是无意义的。内存中变量的布局是会改变的。SubName
/Qopenmp
更正 的长度。请考虑使用可分配的字符标量,使代码能够适应过程名称长度的后续更改。SubName
(存在其他风格或可移植性问题,但它们更主观。
评论