- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would like to develop a Fortran Static Library that include a custom subroutine that takes a long time to complete.
This static library will be linked in my C++ application statically too.
My goal is monitoring that current status of this subroutine in my C++ application in real-time.
So, for each step of a "fortran loop", I would like to send the loop index to my C++ application.
I'm new in Fortran world, so I was thinking that this task could be something like this:
My C++ header:
extern "C" void fortran_status(int* value);
My Fortran-90 file:
module my_interfaces use iso_c_binding interface subroutine fortran_status(progress_value) bind(C, name = 'fortran_status') use, intrinsic :: iso_c_binding integer(c_int), intent(out) :: progress_value end subroutine fortran_status end interface end module my_interfaces ! My long calc subroutine subroutine my_long_calc(progress_value) BIND(C, name = 'my_long_calc') use, intrinsic :: ISO_C_BINDING use my_interfaces implicit none EXTERNAL fortran_status integer (C_INT), INTENT(INOUT) :: progress_value integer (C_INT) :: count do count = 0, 5 progress_value = progress_value + 1 ! Send 'progress_value' to a C++ function: call fortran_status(progress_value) ! Wait 1 second: call sleep(1) end do end subroutine my_long_calc
This code gives me a compile-time error:
error #6406: Conflicting attributes or multiple declaration of name. [FORTRAN_STATUS] C:\Users\lamar\Desktop\Lib1_interface\Lib1.f90 18
I'm using Microsoft Visual Studio 2019 with Intel Visual Fortran (Windows 10 x64).
How could I monitoring that subroutine status? Or get the fortran loop index in my C++ application?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Confused... You say you are using Intel Visual Fortran but you seem to be using gfortran instead. The two do not mix. I can't help you with gfortran issues.
Your sources build and run fine (with some warning messages by MSVC) using Microsoft Visual C++ and Intel Visual Fortran. (I am a bit confused about the MSVC messages, but I ignored them.)
D:\Projects>ifort -c sub.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.4.245 Build 20190417 Copyright (C) 1985-2019 Intel Corporation. All rights reserved. D:\Projects>cl main.cpp sub.obj Microsoft (R) C/C++ Optimizing Compiler Version 19.21.27702.2 for x64 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\ostream(258): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\ostream(249): note: while compiling class template member function 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)' main.cpp(11): note: see reference to function template instantiation 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)' being compiled main.cpp(11): note: see reference to class template instantiation 'std::basic_ostream<char,std::char_traits<char>>' being compiled Microsoft (R) Incremental Linker Version 14.21.27702.2 Copyright (C) Microsoft Corporation. All rights reserved. /out:main.exe main.obj sub.obj D:\Projects>main.exe Monitoring Fortran subroutine... Fortran current status = 0 Fortran current status = 1 Fortran current status = 2 Fortran current status = 3 Fortran current status = 4 Fortran current status = 5 D:\Projects>
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just remove the EXTERNAL declaration - it conflicts with the interface and is unnecessary.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you, Steve!
Could you help me to complete this code example?
Here is my full C++ code:
#include <iostream> extern "C" { void my_long_calc(void); void fortran_status(int* value); } void fortran_status(int* value) { std::cout << "Fortran current status = " << *value << std::endl; } int main (void) { std::cout << "Monitoring Fortran subroutine..." << std::endl; my_long_calc(); return 0; }
And here is my full Fortran-90 code:
module my_interfaces use iso_c_binding interface subroutine fortran_status(progress_value) bind(C, name = 'fortran_status') use, intrinsic :: iso_c_binding integer(c_int), intent(out) :: progress_value end subroutine fortran_status end interface end module my_interfaces ! My long calc subroutine subroutine my_long_calc(progress_value) BIND(C, name = 'my_long_calc') use, intrinsic :: ISO_C_BINDING use my_interfaces implicit none integer (C_INT), INTENT(INOUT) :: progress_value integer (C_INT) :: count do count = 0, 5 progress_value = progress_value + 1 ! Send 'progress_value' to a C++ function: call fortran_status(progress_value) ! Wait 1 second: call sleep(1) end do end subroutine my_long_calc
I compile the fortran code to a Static Library (Lib2.lib) x86 bits using Visual Studio 2019 / Visual Fortran.
Now I'm trying to link the C++ code with Fortran Static Lib using MingW g++:
g++ -Wall -L. .\Lib2.lib -lgfortran .\main.cpp -o app.exe
I got this linker error:
undefined reference to `my_long_calc'
What I have to do?
I'm would like to see this terminal output:
Monitoring Fortran subroutine... Fortran current status = 0 Fortran current status = 1 Fortran current status = 2 Fortran current status = 3 Fortran current status = 4 Fortran current status = 5
Could you help me?
Thank you,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
UPDATE 1:
Now this changed Fortran code compiles and it work well ONLY if I'm using MingW g++ (x86).
Fortran code:
module my_interfaces use iso_c_binding interface subroutine fortran_status(progress_value) bind(C, name = 'fortran_status') use, intrinsic :: iso_c_binding integer(c_int), intent(out) :: progress_value end subroutine fortran_status end interface end module my_interfaces ! My long calc subroutine subroutine my_long_calc() BIND(C, name = 'my_long_calc') use, intrinsic :: ISO_C_BINDING use my_interfaces implicit none integer (C_INT) :: progress_value integer (C_INT) :: count progress_value = 0 do count = 0, 5 progress_value = count ! Send 'progress_value' to a C++ function: call fortran_status(progress_value) ! Wait 1 second: call sleep(1) end do end subroutine my_long_calc
C++ Code:
#include <iostream> extern "C" { void my_long_calc(void); void fortran_status(int* value); } void fortran_status(int* value) { std::cout << "Fortran current status = " << *value << std::endl; } int main (void) { std::cout << "Monitoring Fortran subroutine..." << std::endl; my_long_calc(); return 0; }
Compile c++:
g++ -Wall -c .\main.cpp
Compile fortran:
gfortran -c .\gfortran.f90
Link all together:
g++ .\main.o .\gfortran.o -o app.exe -lgfortran
The problem now is that I need to use Visual Studio 2019 and Visual Fortran to develop my Fortran Code.
And I would like to compile all Fortran code to a single static library (*.lib) file using Visual Studio.
What I need to change to get to link the *.lib file (from Visual Fortran) using the MingW g++ command?
I was thinking to use something like this:
g++ main.cpp my_lib.lib -o app.exe
But I got this linker error:
undefined reference to my_long_calc
What I need to do?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Confused... You say you are using Intel Visual Fortran but you seem to be using gfortran instead. The two do not mix. I can't help you with gfortran issues.
Your sources build and run fine (with some warning messages by MSVC) using Microsoft Visual C++ and Intel Visual Fortran. (I am a bit confused about the MSVC messages, but I ignored them.)
D:\Projects>ifort -c sub.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.4.245 Build 20190417 Copyright (C) 1985-2019 Intel Corporation. All rights reserved. D:\Projects>cl main.cpp sub.obj Microsoft (R) C/C++ Optimizing Compiler Version 19.21.27702.2 for x64 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\ostream(258): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\ostream(249): note: while compiling class template member function 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)' main.cpp(11): note: see reference to function template instantiation 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)' being compiled main.cpp(11): note: see reference to class template instantiation 'std::basic_ostream<char,std::char_traits<char>>' being compiled Microsoft (R) Incremental Linker Version 14.21.27702.2 Copyright (C) Microsoft Corporation. All rights reserved. /out:main.exe main.obj sub.obj D:\Projects>main.exe Monitoring Fortran subroutine... Fortran current status = 0 Fortran current status = 1 Fortran current status = 2 Fortran current status = 3 Fortran current status = 4 Fortran current status = 5 D:\Projects>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve!
Yes, I was trying to mix these 2 compilers: Visual Fortran (Visual Studio) + MingW g++.
The main idea is to develop a cross-plataform application...so I would like to write a Fortran code that can be compile in Windows and Linux environment.
Well, about the code above...I compiled it in Visual Fortran and linked well using QT Creator (qmake). Works good on Windows!
Thanks for your help...
Now I'm trying to send a Fortran string to my C++ application...
I started from this fortran/c++ example that is running, and I tried to change only the Interface to send a fortran string...but it's not working...
Please, could you help me?
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/815905
Steve! Thank you so much!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am unsure how Intel Fortran-compiled sources work when mixed with g++ in MingW. It's not a combination I would recommend. You're doing well to use Fortran's C interoperability features and, done correctly, it should be portable (that is the whole idea of those features!)
I answered your string issue in the other thread.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maia, Nycholas wrote:..
The problem now is that I need to use Visual Studio 2019 and Visual Fortran to develop my Fortran Code.
And I would like to compile all Fortran code to a single static library (*.lib) file using Visual Studio.What I need to change to get to link the *.lib file (from Visual Fortran) using the MingW g++ command? ..
@Maia, Nycholas.
Note on Windows, instead of a static library, you can work with a dynamic library (DLL) i.e., you can compile using Intel Fortran and link your Fortran code as a DLL, either from the command line or using Visual Studio (preferably) and consume it from a C++ program built using GCC and MinGW. See an example below using the command line - note the same idea holds true using Visual Studio. If this looks an option for you i.e., working with a DLL, you can check whether the same approach using a "shared" library can work for you on other platforms of interest (Linux?).
Fortran code: note some changes with abstract interfaces, use of module for all Fortran procedures, and use of a default message writer:
module my_interfaces use, intrinsic :: iso_c_binding, only : c_char, c_size_t abstract interface subroutine Ifortran_message(msg, lenmsg) bind(C) import :: c_char, c_size_t implicit none ! Argument list character(kind=c_char, len=1), intent(in) :: msg(*) integer(c_size_t), intent(in), value :: lenmsg end subroutine Ifortran_message end interface end module my_interfaces module my_long_calc_m use, intrinsic :: iso_c_binding, only : c_char, c_size_t, c_funptr, c_f_procpointer use, intrinsic :: iso_fortran_env, only : stdout => output_unit use my_interfaces, only : Ifortran_message implicit none procedure(Ifortran_message), pointer :: pMessageWriter => DefaultMessageWriter contains ! My long calc subroutine subroutine my_long_calc() bind(C, name="my_long_calc") ! A single variable: character(kind=c_char, len=:), allocatable :: msg integer(c_size_t) :: lenmsg msg = "this is a msg from fortran" lenmsg = len_trim(msg, kind=kind(lenmsg) ) ! Send a message to the C++ application: call pMessageWriter(msg, lenmsg) return end subroutine my_long_calc subroutine SetMessageWriter( pWriter ) bind(C, name="SetMessageWriter" ) ! Argument list type(c_funptr), intent(in), value :: pWriter call c_f_procpointer( cptr=pWriter, fptr=pMessageWriter ) return end subroutine subroutine DefaultMessageWriter( msg, lenmsg ) bind(C, name="DefaultMessageWriter" ) ! Argument list character(kind=c_char, len=1), intent(in) :: msg(*) integer(c_size_t), intent(in), value :: lenmsg ! Error handling elided e.g., lenmsg <= 0 write( stdout, fmt="(*(g0))" ) msg(1:lenmsg) return end subroutine DefaultMessageWriter end module
Use of a Windows definition file to handle exported symbols of your DLL:
LIBRARY my_long_calc EXPORTS my_long_calc @1 SetMessageWriter @2
C++ main program: use a typedef for a function pointer
#include <iostream> typedef void (* pMessageWriter)( char*, size_t ); extern "C" { void my_long_calc(void); void SetMessageWriter( pMessageWriter ); } void MyWriter(char* msg, size_t lenmsg) { std::cout.write( msg, lenmsg ); } int main(int argc, char *argv[]) { SetMessageWriter( MyWriter ); my_long_calc(); return 0; }
Compile and link steps:
C:\Temp>ifort /standard-semantics /c /warn:all /stand:f18 my_long_calc.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.1.0.085 Pre-Release Beta Build 20190522 Copyright (C) 1985-2019 Intel Corporation. All rights reserved. ifort: NOTE: The Beta evaluation period for this product ends on 9-oct-2019 UTC. C:\Temp>link /DLL /DEF:my_long_calc.def /subsystem:windows my_long_calc.obj /out:my_long_calc.dll Microsoft (R) Incremental Linker Version 14.21.27702.2 Copyright (C) Microsoft Corporation. All rights reserved. Creating library libmy_long_calc.lib and object libmy_long_calc.exp C:\Temp>g++ -Wall -c main.cpp C:\Temp>g++ main.o -o main.exe -lmy_long_calc -Lc:\temp C:\Temp>dir lib*.* Volume in drive C is OSDisk Volume Serial Number is .. Directory of C:\Temp 08/13/2019 05:21 PM 544,768 libmy_long_calc.dll 08/13/2019 05:21 PM 952 libmy_long_calc.exp 08/13/2019 05:16 PM 2,112 libmy_long_calc.lib .. C:\Temp>
Upon execution:
C:\Temp>main.exe this is a msg from fortran C:\Temp>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@FortranFan, thank you for your good explanation!
I will try!
Thanks,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@FortranFan,
Thank about your information about DLL on Windows, but I really would like to create a fortran static library for other reasons.
I'm developing some plugins with UI for a other main application...and these plugins should be a mix of QT GUI + Fortran and C++ code.
For each developed plugin, I would like to build 2 output files:
1- A single *.dll file (Windows)
2- A single *.so file (Linux)
To build these plugins (dynamic libraries) above, I'm doing like this:
1- Write the "plugin X" Fortran source code and compile it to a static library (*.dll) and (*.a)
2- Write the "plugin X" C++ and QT UI source code using QT Creator IDE
3- Config QT Creator IDE to build a "shared library" output (*.dll) and (*.so).
4- Generate the final plugin file (*.dll) or (*.so) compiling the C++/UI code and linking it statically with the fortran static library.
So, my "plugin X" is a single file "shared library" (*.dll or *.so), but it have a Fortran static library inside of it.
I tried to test your Fortran code above, it compiles ok and I got the static library file using Visual Fortran, but I got linker errors on QT Creator IDE.
unresolved external symbol for_dealloc_allocatable referenced in function my_long_calc unresolved external symbol for_alloc_allocatable referenced in function my_long_calc unresolved external symbol for_len_trim referenced in function my_long_calc unresolved external symbol c_f_pointer_set_scalar referenced in function SetMessageWriter unresolved external symbol for_write_seq_fmt referenced in function DefaultMessageWriter
And a single C++ warning:
warning: implicit conversion changes signedness: 'size_t' (aka 'unsigned long long') to 'std::streamsize' (aka 'long long')
You already explain a lot to me about Fortran, but could you help me to complete this example?
I need to generate a cross-platform Fortran static library (*.lib using Visual Fortran) and (*.so using g++) and then link it statically with my QT C++ code.
@Steve, you are welcome too for any ideas, suggestions, improvements....
Thank you for your help,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maia, Nycholas wrote:.. I tried to test your Fortran code above, it compiles ok and I got the static library file using Visual Fortran, but I got linker errors on QT Creator IDE...
I know little about Qt Creator IDE but as you were advised in Quote #7, mixing libraries during linking - as you are attempting using static library with Intel Fortran and linking that with code compiled using another processor - is generally a recipe for failure. You may be familiar with this page:
https://doc.qt.io/qtcreator/creator-tool-chains.html
You may be able to follow instructions on above page to specify your toolchains. I'll suggest you either work with compatible processors (e.g., Intel Fortran compiler + Intel C++ on Windows, Linux; Intel Fortran + Microsoft C/C++ on Windows; or gfortran compiler + Microsoft C/C++ on Windows; or gfortran compiler + g++ on Windows, Linux) or consider the run-time invocations as per the DLL/so option.
Maia, Nycholas wrote:.. single C++ warning ...
You can get rid of this warning as follows:
void MyWriter(char* msg, size_t lenmsg) { std::cout.write( msg, static_cast<std::streamsize>(lenmsg) ); }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, @FortranFan... now I know about the C++/Fortran compiler differences.
So, why Am'I trying to do it using QT Creator IDE and not using only MSVC (Visual Fortran) + Intel Fortran?
This project must be cross-platform (Windows and Linux), (maybe Mac too) and this application will have GUI (window, buttons, labels, etc...).
I think that QT with QT Creator IDE is a good choose to do that.
QT Creator IDE can be configured to compile QT projects using installed Microsoft Visual C++. I attached my QT compiler configuration here that shows that I'm using Microsoft Visual C++ 16.1 (x86_amd64) to compile my QT projects.
So, in the background, my tools are:
Windows 10 x64 environment:
Fortran Compiler: Visual Fortran 2019 (running inside Visual Studio 2019)
C++ Compiler: Microsoft Visual C++ 16.1 (running inside QT Creator IDE)
Linux Ubuntu 18 x64 environment:
Fortran Compiler: gfortran (terminal)
C++ Compiler: g++ (terminal)
So, I believe that I'am be able to mix the fortran static library with QT C++ UI, right?
Let's try to focus in Windows environment only now, ok?
Do you have any ideas why I'm getting these linker errors above?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maia, Nycholas wrote:Yes, @FortranFan... now I know about the C++/Fortran compiler differences. ..
Do you have any ideas why I'm getting these linker errors above? ..
So your attached image suggests the Fortran and C++ processors are compatible - Intel Fortran and Microsoft Visual C++ - assuming that is indeed the case, my suggestion will be to check your library path settings in Qt Creator IDE and ensure the right Intel Fortran compiler related libraries are picked up during the link step. Toward this, this page which details the settings for Visual Studio IDE might help you cross-check what you have in Qt Creator IDE currently, or what might be missing. My hunch is once you make sure the right libraries become known to your linker via suitable settings in the IDE, your link errors will be resolved:
https://software.intel.com/en-us/articles/configuring-visual-studio-for-mixed-language-applications
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Nycholas, I am also building a Qt GUI with a Fortran engine. In Qt Creator I link several static libraries (VTK) and several dynamic libraries, including my own Fortran library. I had to ensure that the Qt Creator toolchain was consistent with the Qt version and with the compiler version used to build the VTK static libraries. I did not have a version of Intel Fortran compatible with the toolset, but building my Fortran library as a DLL (in Windows) avoided the problem. I appreciate that your situation is a bit different, since you want to produce a single DLL, while I am building an executable and it's no problem to distribute the DLL to other users of the program.
Sometimes the order of the static libraries in Qt Creator is important - this is a possible cause of your link errors. The dependent library must be processed before the library that satisfies the dependency:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Now, I got it working perfectly fine! Thank you so much @Steve for your patience and quick reponses!
Just to help other people...here is my full example about how to use C/C++ and Fortran with Interoperability (ISO 2003).
This example below sends data from a C++ application to a Fortran Static Library and get back some results in C++ application:
My C++ code:
#include <iostream> extern "C" { void fortran_subroutine(int input1, double* input2, int* input3, size_t input4); void fortran_return(int by_value, double* by_ref, char* string, int* array, size_t len_array); } void fortran_return(int by_value, double* by_ref, char* string, int* array, size_t len_array) { std::cout << "by_value: " << by_value << std::endl; std::cout << "by_ref: " << *by_ref << std::endl; std::cout << "string: " << string << std::endl; for (size_t i = 0; i < len_array; i++ ) { std::cout << "array[" << i << "] = " << array << std::endl; } } int main(int argc, char* argv[]) { // Init C++ input variables: int x = 25; double y = 0.12345; int z[] = {1, 2, 3, 4, 5}; size_t z_size = sizeof(z)/sizeof(z[0]); // Send 'x' and 'z_size' by value and send 'y' and 'z' by reference to Fortran subroutine: fortran_subroutine(x, &y, z, z_size); return 0; }
My Fortran code:
! My ISO 2003 C Bind Interface module my_interfaces interface subroutine fortran_return(a, b, d, e, f) bind(C) use, intrinsic :: ISO_C_BINDING ! Pass 'a' by value: integer(C_INT), intent(in), value :: a ! Pass 'b' by reference: real(C_DOUBLE), intent(in) :: b ! Pass 'd' string by reference with 'C NULL CHARACTER': character(kind=C_CHAR), intent(in) :: d(*) ! Pass 'f' by value, and declared BEFORE 'e' (compile dependency) INTEGER(C_SIZE_T), INTENT(IN), value :: f ! Pass 'e' array by reference: integer(C_INT), DIMENSION(f), INTENT(IN) :: e end subroutine fortran_return end interface end module my_interfaces ! My Fortran subroutine subroutine fortran_subroutine(x, y, z, n) bind(C) use, intrinsic :: ISO_C_BINDING use my_interfaces implicit none !====== ISO BIND ARGUMENTS =====! ! Get 'x' from C++ by value: integer(C_INT), intent(in), value :: x ! Get 'y' from C++ by reference: real(C_DOUBLE), intent(in) :: y ! Get 'z' array from C++ by reference: integer(C_INT), DIMENSION(n), INTENT(INOUT) :: z ! Get 'n' size from C++ by value: INTEGER(C_SIZE_T), INTENT(IN), value :: n !============================ ! Temp internal variable: integer(C_INT) :: count ! Declare the same type of Fortran 'interface' arguments: integer(C_INT) :: my_int real(C_DOUBLE) :: my_double character(kind=C_CHAR, len=50) :: my_str ! Init variables / do some stuff: my_int = x + 1 my_double = y + 1 my_str = "Hello from Fortran"//C_NULL_CHAR FORALL (count = 1:n) z(count) = 1 ! Call C++ function: call fortran_return(my_int, my_double, my_str, z, n) end subroutine fortran_subroutine
Step 1: Compilers
Your Fortran and C/C++ compilers MUST BE COMPATIBLE EACH OTHER.
So, in Windows environment use:
-> C++: Microsoft Visual C++
-> Fortran: Intel Visual Fortran
In Linux environment use:
-> C++: GCC (yes, gcc compiles C++ code too...)
-> Fortran: gfortran
In Mac OSX environment use:
-> C++: Clang
-> Fortran: gfortran
I tested this simple example on these 3 environments and it works well.
Warning: Do NOT mix uncompatible compilers like: gcc with Intel Visual Fortran. It doesn't work!
Step 2: IDE's
If you are using compatible compilers, you can change the IDE. I tested my C++ code using Qt Creator IDE with MSVC compiler. It works great!
Step 3: Qt Creator configurations (only for Qt Creator IDE users)
If you are in Linux environment together with Qt Creator IDE, you have to just add your compiled Fortran Library using Qt Creator Wizard and the link is done.
But if you are in Windows environment with Qt Creator IDE, add your Fortran compiled library (*.lib or *.a) with Qt Creator Wizard AND add this line in the *.pro file:
LIBS += -L"<full path to Intel Visual Fortran Compiler folder>/lib/intel64_win"
Obs. 1: In my machine, I have installed IVF 2019, so this folder is in:
C:/Program Files (x86)/IntelSWTools/compilers_and_libraries_2019.4.245/windows/compiler
Obs. 2: Be careful about select the correct 32 bits or 64 bits IVF folder
Step 4: Visual Studio IDE
If you are using Microsoft Visual Studio IDE you have to link your Fortran Static Library with your C/C++ application too.
I not tested this setup, but is easy to find how to do it on internet.
Step 5: Intel Visual Fortran
If you are building a Fortran Static Library using Visual Studio 2019, check this configurations:
Project Properties -> Fortran -> Libraries:
- Run-time: Multithreaded
- Disable Default Library Search Rules: No
- Disable OBJCOMMENT Library Names in Object: No
Project Properties -> Fortran -> Librarian -> General:
- Link Library Dependencies: Yes
Build and Run!
The output should be like this:
by_value: 26 by_ref: 1.12345 string: Hello from Fortran array[0] = 1 array[1] = 1 array[2] = 1 array[3] = 1 array[4] = 1
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page