【发布时间】:2018-06-04 06:41:50
【问题描述】:
我写了一些代码来加载一个用 Fortran 编译的动态库。 Fortran 库中的导出函数包括导出的 setter 和 getter。我正在尝试使用 Windows API 加载这些 setter 和 getter。虽然这适用于我在调试中构建的代码。它不适用于我的内置版本代码。在发布时,当我尝试将1.0f 传递给set() 时,当我进入fortran 代码时,我在调试器中看到0.0f。
编辑:我忘记提及的另一个观察结果。如果我只加载setValue() 函数。我的问题完全消失了。只有当我从库中加载其他函数时,我才会开始遇到我所看到的问题。
编译器
- 英特尔 Fortran 2017 更新 5
- Visual Studio 2017 v15.5.2
调试
我已经确定,当我的 C++ 代码在发行版中编译时,我加载的 set() 函数会将 0.0f 传递给 fortran 函数。这是通过加载 fortran 库的调试版本并通过 Visual Studio 的调试器运行它来发现的。对我的代码的调试版本执行相同的操作会产生正确的值并传递给 fortran 函数。
我尝试了以下方法试图弄清楚发生了什么:
- 尝试在我的加载程序的调试和发布版本中加载已编译 Fortran 的调试和发布二进制文件。仅适用于我的加载程序的调试版本。
- 重建了 Fortran 代码以验证编译器标志,例如用于调试的多线程调试 DLL 和用于发布的多线程 DLL。
- 执行了 fortran 二进制文件的转储程序以验证函数地址是否正确加载;他们是。
FORTRAN
REAL FUNCTION getValue()
!DEC$ ATTRIBUTES DLLEXPORT, c:: getValue
IMPLICIT NONE
INCLUDE 'VALUE.CMN'
getValue = VAL
RETURN
END FUNCTION getValue
SUBROUTINE setValue(x)
!DEC$ ATTRIBUTES DLLEXPORT, c:: setValue
IMPLICIT NONE
INCLUDE 'VALUE.CMN'
REAL, INTENT(IN) :: x
VAL = x
END SUBROUTINE setValue
C++
const auto handle = reinterpret_cast<HMODULE>(LoadLibrary("fortran_value.dll"));
typedef void(*Set)(float&);
typedef float(*Get)(void);
const auto set = reinterpret_cast<Set>(GetProcAddress(handle, "setvalue"));
const auto get = reinterpret_cast<Get>(GetProcAddress(handle, "getvalue"));
auto value = 1.0f;
// 0.0f gets set to the internal fotran variable when this code is compile in release.
set(value);
// Only succeeds when this code is compiled in Debug.
// get() returns 0.0f when this code is compiled in Release.
if(value == get())
{
std::cout << "Success!\n";
}
else
{
std::cout << "Fail!\n";
}
FreeLibrary(handle);
我很茫然。对这里可能发生的事情有什么想法或建议吗?
完整的可编译示例
以下是我遇到的问题的完整可编译示例的链接。在有更多的时间花在它身上之后。看来我的问题源于我尝试使用上述代码制作包装器。
【问题讨论】:
-
什么是“不起作用”?究竟会发生什么?有什么错误信息吗?
-
我用一些解释我从调试器看到的值的 cmets 更新了我的 C++ 代码。在发布时,我通过
set()传递了 1.0f,但在单步执行 fortran 代码时,我看到了 0.0f。在调试中,它按预期工作,我将 1.0f 传入,我在调试器中看到 1.0f。 -
非常、非常怀疑在调试器中检查变量时所看到的内容。我强烈建议单步执行汇编程序指令,并查看它在做什么。
-
这是 32 位还是 64 位?我认为您的调用约定不匹配,或者您对调试器显示的内容感到困惑。
-
这只是 64 位。我的机器上只安装了 64 位 fortran 编译器。
标签: c++ visual-studio dll fortran intel-fortran