Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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
C++ 从动态库加载Fortran函数:调试与发布_C++_Visual Studio_Dll_Fortran_Intel Fortran - Fatal编程技术网

C++ 从动态库加载Fortran函数:调试与发布

C++ 从动态库加载Fortran函数:调试与发布,c++,visual-studio,dll,fortran,intel-fortran,C++,Visual Studio,Dll,Fortran,Intel Fortran,我编写了一些代码来加载用Fortran编译的动态库。Fortran库中导出的函数中有导出的setter和getter。我正在尝试使用Windows API加载这些setter和getter。而这适用于我的代码内置调试。它不适用于我的代码内置版本。在发行版中,当我尝试将1.0f传递到set()时,当我进入fortran代码时,我在调试器中看到0.0f 编辑:另一个我忘了提到的观察结果。如果我只加载setValue()函数。我的问题完全解决了。只有当我从库中加载其他函数时,我才开始出现我看到的问题

我编写了一些代码来加载用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()//Cuff>函数将通过<代码> 0.0f 到FORTRAN函数。这是通过加载fortran库的调试版本并通过Visual Studio的调试器运行发现的。对我的代码的调试构建执行相同的操作会产生传递给fortran函数的正确值

为了弄清发生了什么,我尝试了以下方法:

  • 尝试在我的加载程序的调试版本和发布版本中加载已编译Fortran的调试和发布二进制文件。仅适用于我的加载程序调试版本
  • 重新生成Fortran代码验证编译器标志,例如用于调试的多线程调试DLL和用于发布的多线程DLL
  • 执行fortran二进制文件的dumpbin,以验证函数地址是否正确加载;是的
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);
const auto handle=reinterpret_cast(加载库(“fortran_value.dll”);
类型定义无效(*套)(浮动和);
类型定义浮动(*Get)(无效);
const auto set=reinterpret_cast(GetProcAddress(句柄,“setvalue”);
const auto get=reinterpret_cast(GetProcAddress(句柄,“getvalue”);
自动值=1.0f;
//在版本中编译此代码时,将0.0f设置为内部fotran变量。
设置(值);
//仅在调试中编译此代码时成功。
//在版本中编译此代码时,get()返回0.0f。
if(value==get())
{

std::cout在阅读了对我的问题的回答之后,我花了更多的时间调试fortran代码并做了更多的研究。正如在对我的问题的回答中所讨论的,调用约定不匹配。通过在我的fortran代码中使用bind(c),我的问题得到了解决

自Fortran 2003(ISO/IEC 1539-1:2004(E))以来,有一种标准化的方法来生成过程和派生类型声明以及与C(ISO/IEC 9899:1999)互操作的全局变量属性已添加,以通知编译器符号应可与C互操作;此外,还添加了一些约束。但是,请注意,并非所有C功能都具有Fortran等效项,反之亦然。例如,C的无符号整数或具有可变参数数的C函数在Fortran中都没有等效项>
什么是“不工作”?到底发生了什么?有什么错误消息吗?我更新了我的C++代码,有一些注释解释了我在调试器中看到的值。在发行版中,我通过1.0f通过代码> SET()。
但是当我单步执行fortran代码时,我看到的是0.0f。在调试中,它按预期工作,我传入1.0f,在调试器中看到的是1.0f。请非常非常怀疑在调试器中检查变量时看到的内容。我强烈建议单步执行汇编程序指令,并查看它正在执行的操作。这是吗是32位还是64位?我想您的调用约定不匹配,或者您对调试器显示的内容感到困惑。这只是64位。我的计算机上只安装了64位fortran编译器。
    REAL FUNCTION getValue() bind(c)
!DEC$ ATTRIBUTES DLLEXPORT :: getValue
    IMPLICIT NONE
    INCLUDE 'VALUE.CMN'

    getValue = VAL
    RETURN
      END FUNCTION getValue

    SUBROUTINE setValue(x) bind(c)
!DEC$ ATTRIBUTES DLLEXPORT :: setValue
    IMPLICIT NONE 
    INCLUDE 'VALUE.CMN'

    REAL, INTENT(IN) :: x

    VAL = x 

      END SUBROUTINE setValue