2017-08-02 88 views
0

我正试图将一个非常简单的C++函数链接到非常简单的英特尔Visual Fortran程序。将英特尔Visual Fortran程序链接到C++函数时遇到问题

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); 

}   

我研究过这个问题他们在Google上尝试了很多种不同的设置,声明,装饰等几十种排列和组合,但都无济于事。事实上,许多职位都很长并且相当复杂,而且往往似乎没有取得圆满结果。

在其他的事情,我曾尝试:

  1. 使得C++代码的.lib
  2. 使得使用各种形式的.DLL
  3. 的C++代码DEC $ ATTRIBUTES装饰,别名:!“ SimpleTest1"
  4. 使用BIND(C,...)使用使用装饰别名
  5. 平原别名
  6. 使用DUMPBIN使用前导的extern“C”
  7. 编译为C代码,看看在.DLL
  8. 符号210
  9. (禁用所有的C++构建体)

和很多其他的事情。我已经尝试了所有可能为其他海报工作的东西,绝对没有运气。

不管我做什么,我得到的功能_MAIN__

按照英特尔的地盘,我在CppResponder.DLL添加就像在源添加引用一个未解决的外部符号_SIMPLETEST1链接错误LNK2019消息文件。

如果有问题,我正在使用适用于Windows的Visual Studio Enterprise 2017和Intel Parallel Studio XE 2016 Update 4作曲家版,所有版本都在64位Windows 8.1机器上运行。

假设英特尔Fortran确实可以调用C++函数(我假设它可以),那么我必须缺少开关或设置某处。我已经使用Visual Studio提供的默认值设置了Fortran和C++项目。这两个项目都设置为Release | 86。

当然,这确实不能做那件难事。我已经花了大约12个小时,没有什么可以展示的。我在Fortran方面有数十年的经验,但对C++来说相当新颖。

有没有人以前做过这件事,并会愿意走过我如何做到这一点?

由于提前,

鲍勃·凯泽

+0

无法解决您的问题,但我可能会为您添加一块拼图。你将不得不声明C++函数为extern“C”,因为fortran永远不会理解C++名称的改变(按照https://people.sc.fsu.edu/~jburkardt/f_src/f90_calls_c++/f90_calls_c++.html) – systemcpro

+0

谢谢,我试过了,就像你在网站上看到的那样,但是这似乎并没有成功。我必须在某个地方失去某些东西。 –

回答

0

cppresponder.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 
+0

谢谢,我希望使用英特尔Fortran和Visual Studio来完成此任务。如果英特尔路线空白,我会研究这一点。 –

+0

啊!我没有VS在那里尝试。但是,由于使用gcc工具链可以正常工作,所以翻译起来可能不太难。我不知道有关微软的东西。无论如何,如果它有任何帮助,那么好,如果不是,那么我们可以称之为研究实验:) – systemcpro

0

我要感谢上述反应。我尝试了他们的建议,但没有得到任何地方。

但经过更多的悲伤,我找到了一些工作。

的Fortran:

program VFTestBed 

use INTERFACES 

integer pInteger 

pInteger = 11 

call SimpleTest1(pInteger) 

end program 



MODULE INTERFACES 

interface 

subroutine SimpleTest1(pInteger) 

!DEC$ ATTRIBUTES ALIAS:'[email protected]@[email protected]' :: 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改变为用于DUMPBIN找出C++名称修饰
  5. 在主程序的.lib
  6. 中添加的接口添加使用接口
  7. :DEC $ ATTRIBUTES ALIAS: '?SimpleTest1 @@ YGXPAH @ Z' :: SimpleTest1

所以,这一切得到的代码不超过30行编译,链接和运行!啧!

15+小时的生活我永远不会回来。

无论如何,它已经解决了,我希望我挽救了一些未来的读者,使我从所经历的悲痛中解脱出来。我希望某个地方的人认为这很有用。

相关问题