【问题标题】:Trouble linking an Intel Visual Fortran Program to a C++ function将英特尔 Visual Fortran 程序链接到 C++ 函数时出现问题
【发布时间】:2017-08-02 03:08:12
【问题描述】:

我正在尝试将一个非常简单的 C++ 函数链接到一个非常简单的 Intel Visual Fortran 程序。

Fortran 程序在一个名为 VFTestBed.f90 的文件中是这样的:

 program VFTestBed

 integer pInteger

 pInteger = 11

 call SimpleTest1( pInteger )

 end program

Fortran 接口块如下所示(在名为 interfaces.f90 的文件中):

MODULE INTERFACES

interface

subroutine SimpleTest1( pInteger) 

!DEC$ATTRIBUTES DECORATE, ALIAS: "SimpleTest1"

integer pInteger

end subroutine SimpleTest1

end interface

END MODULE

C++ 函数如下所示(在名为 cppresponder.cpp 的文件中):

#include <windows.h>
#include <sstream>

void SimpleTest1(int pInteger);

void SimpleTest1(  int pInteger)

{

      std::string pString = "";
      std::string pTitle = "";

      std::string pName = "SimpleTest1\0";

   pString = "Integer was entered.";
   pTitle = "In Routine: " + pName;

   MessageBoxA(NULL, pString.c_str(), pTitle.c_str(), MB_OK |    MB_ICONINFORMATION);

}        

我在谷歌上研究过这个问题,尝试了几十种各种设置、声明、装饰等的排列和组合,但都无济于事。事实上,许多帖子都很长而且相当复杂,而且往往似乎没有得出一个成功的结论。

在我尝试过的其他事情中:

  1. 使 C++ 代码成为 .LIB
  2. 将 C++ 代码制作为 .DLL
  3. 使用各种形式的 !DEC$ATTRIBUTES DECORATE,别名:“SimpleTest1”
  4. 使用 BIND(C, ...)
  5. 使用普通别名
  6. 使用修饰别名
  7. 使用 DUMPBIN 查看 .DLL 中的符号
  8. 使用前导extern "C"
  9. 编译为 C 代码(禁用所有 C++ 结构)

还有很多其他的东西。我已经尝试了所有可能对其他海报有用的东西,但绝对没有运气。

无论我做什么,我都会收到一条链接器错误消息 LNK2019,关于函数 _MAIN__ 中引用的未解析的外部符号 _SIMPLETEST1

根据英特尔网站,我在 CppResponder.DLL 中添加了,就像在源文件中添加一样。

如果重要的话,我正在使用适用于 Windows 的 Visual Studio Enterprise 2017 和 Intel Parallel Studio XE 2016 Update 4 composer Edition,它们都在 64 位 Windows 8.1 机器上运行。

假设 Intel Fortran 确实可以调用 C++ 函数(我假设它可以),那么我一定是在某处缺少开关或设置。我已经使用 Visual Studio 提供的默认值设置了 Fortran 和 C++ 项目。两个项目都设置为 Release | x86。

当然,这真的不是那么难的事情。我在这上面花了大约 12 个小时,但没有什么可展示的。我在 Fortran 方面有数十年的经验,但对 C++ 还很陌生。

以前有没有人这样做过并且愿意告诉我你是怎么做到的?

提前致谢,

鲍勃·凯瑟

【问题讨论】:

  • 无法解决您的问题,但我也许可以为您添加一块拼图。您必须将 C++ 函数声明为 extern "C",因为 fortran 永远不会理解 C++ 名称修饰(根据此处people.sc.fsu.edu/~jburkardt/f_src/f90_calls_c++/…
  • 谢谢,我试过了,就像你提到的网站上显示的那样,但这似乎没有奏效。我一定还在某处遗漏了什么。

标签: c++ visual-studio dll intel-fortran name-decoration


【解决方案1】:

cpresponder.cpp

#include <iostream>

extern "C" void simpletest_(int* i){
    std::cout << "cpp " << *i << '\n';
}

VFTestBed.cpp

 program VFTestBed

 integer pInteger

 pInteger = 11

 call simpletest(pInteger)

 end program

编译:

g++ -c cppresponder.cpp; gfortran -c VFTestBed.f90; gfortran -o test.o cppresponder.o VFTestBed.o -l stdc++

执行:

./test.o

输出

>cpp 11

您可能还需要这些编译器开关

 g++ -c -Wpadded -Wpacked -malign-double -mpreferred-stack-boundary=8 cppresponder.cpp; gfortran -c -malign-double VFTestBed.f90

【讨论】:

  • 谢谢,我希望使用 Intel Fortran 和 Visual Studio 完成这项任务。如果英特尔路线空无一人,我会调查此事。
  • 啊!我没有VS在那里尝试。但是,由于使用 gcc 工具链可以正常工作,因此翻译起来可能并不难。不过我对微软的东西一无所知。无论如何,如果它有任何帮助,那么很好,如果没有,那么我们可以称之为研究实验:)
【解决方案2】:

感谢以上回复者。我尝试了他们的建议,但没有成功。

但是在经历了更多的悲伤之后,我确实找到了一些有用的东西。

Fortran:

program VFTestBed

use INTERFACES

integer pInteger

pInteger = 11

call SimpleTest1( pInteger )

end program



MODULE INTERFACES

interface

subroutine SimpleTest1( pInteger)

!DEC$ ATTRIBUTES  ALIAS:'?SimpleTest1@@YGXPAH@Z' :: SimpleTest1

integer pInteger

end subroutine SimpleTest1

end interface

END MODULE

在 C++ 方面:

#define WIN32_DEFAULT_LIBS
#include <windows.h>
#include <iostream>
#include <sstream>


__declspec(dllexport) void SimpleTest1(int* pInteger);

void SimpleTest1(int* pInteger)

{

    std::string pString = "";
    std::string pTitle = "";

    std::string pName = "SimpleTest1\0";

    pString = "Integer entered = " + std::to_string(*pInteger);
    pTitle = "In Routine: " + pName;

    MessageBoxA(NULL, pString.c_str(), pTitle.c_str(), MB_OK |    MB_ICONINFORMATION);


}

显着变化:

  1. 添加了 __declspec(dllexport)
  2. 将 int 更改为 int*
  3. 添加了#define WIN32_DEFAULT_LIBS
  4. 从 .DLL 更改为 .LIB
  5. 使用 DUMPBIN 找出 C++ 名称装饰
  6. 在主程序中添加了 USE INTERFACES
  7. 在界面中添加:!DEC$ ATTRIBUTES ALIAS:'?SimpleTest1@@YGXPAH@Z' :: SimpleTest1

所以,所有这些都只需要不到 30 行代码即可编译、链接和运行!嘘!

我生命中超过 15 小时的时间我再也回不来了。

无论如何,它已经解决了,我希望我已经从我所经历的所有悲伤中拯救了一些未来的读者。我希望某个地方的人会觉得这很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    相关资源
    最近更新 更多