2017-08-02 71 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+小時的生活我永遠不會回來。

無論如何,它已經解決了,我希望我挽救了一些未來的讀者,使我從所經歷的悲痛中解脫出來。我希望某個地方的人認爲這很有用。