- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to call a C++ subroutine from fortran. This should not be hard and there have been posts about it before. I think I have read all them and also read the Intel literature. I am using Visual Studio 2019 Parallel Studio 2020 with just Fortran. I am using the VS IDE, not a command line. I have a solution with two projects in it, one fortran and one C++. The fortran project has two files, testF.f and adModule.f. They are shown below, testF.f first
program tryadd
USE first_try_mod
implicit none
real X1
real Y1
real Z1
C external firstadd !$pragma C( firstadd )
x1 = 1.0
y1 = 4.0
z1 = 5.0
call FIRSTADD (X1,Y1,Z1 )
C write( *,"z1 = ")
end program tryadd
Then the module file
MODULE first_try_Mod
interface
C subroutine TESTADD( X1,Y1,Z1) bind(C,name='TESTADD')
subroutine TESTADD( X1,Y1,Z1)
!DEC$ ATTRIBUTES C, REFERENCE, ALIAS : '_TESTADD' :: TESTADD
!DEC$ ATTRIBUTES REFERENCE :: X1,Y1,Z1
C subroutine testadd() bind(C,name='testadd')
C real, value :: X1
C real, value :: Y1
C real, value :: Z1
real :: X1
real :: Y1
real :: Z1
end subroutine TESTADD
end interface
C
END MODULE first_try_Mod
You can see some things commented out; I have tried about a hundred different things and commented what I am not presently trying.
The C++ project has two files, testC.h and testC.cpp as shown below, 1 line header first
void TESTADD (float *X1, float *Y1, float *Z1);
testC.cpp next
#include <windows.h>
#include <iostream>
using namespace std;
extern "C"
{
void TESTADD (float *X1, float *Y1, float *Z1);
void TESTADD (float *X1, float *Y1, float *Z1
// __declspec(dllexport) void testadd (float *x1, float *y1, float *z1);
// __declspec(dllexport) void testadd (float *x1, float *y1, float *z1
)
{
*Z1 = *Y1 + *X1;
}
}
For each one of the hundred things I have tried when I build I get the error
fatal error LNK1561: entry point must be defined
Can anybody tell me a solution to this?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Use Cinteroperability to declare the subroutine parameters, e.g.
use_iso_c_binding
real(c_float) :: X1
Stick with the bind(C,name=...) method, but make the name agree with respect to case (C is case-sensitive). If you really want to call the C++ function TESTADD, then you'll need (the Fortran name is irrelevant):
subroutine testadd( X1,Y1,Z1) bind(C,name='TESTADD')
use_iso_c_binding
real(c_float) :: X1, Y1, Z1
You are passing the arguments by reference, not by value, so don't use "value". Why not use free format, .f90?
On the C side, you want:
extern "C"
{
void TESTADD (float *X1, float *Y1, float *Z1);
{
*Z1 = *Y1 + *X1;
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ok thanks, I will try it
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, I just noticed that your main program does this:
call FIRSTADD (X1,Y1,Z1 )
but your subroutine is called TESTADD. You can change the subroutine name to FIRSTADD without changing anything else - the "name" clause will take care of the C linkage.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
G.Thomann wrote:For each one of the hundred things I have tried when I build I get the error
fatal error LNK1561: entry point must be defined
Can anybody tell me a solution to this?
That's probably caused by attempting to compile and link the C source by itself into an EXE. What is the nature of the C++ project? Library? EXE?
A related question: have you configured the dependence of the Fortran project on the C++ library?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think you also need:
extern "C"
before the declarations of TESTADD in the C++ code, otherwise you're going to get C++ name mangling.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Steve Does he need to move 'extern "C"' up to the top of the program?
Unless what he's showing is not his actual code, the problem is that his main program is calling FIRSTADD, not TESTADD.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's certainly one of the issues. But I admit I missed that extern "C" was there bracketing the declarations, so that part should be ok.
In the Fortran code, I see that the use of BIND(C) has been commented out and the non-standard directives used instead, which is not something I would recommend. With BIND(C) as shown, the interface looks correct to me, and it would be inappropriate to use VALUE, since the prototype in C++ accepts the arguments by reference.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for all the comments. Call the wrong subroutine name from the fortran code was dumb. Unfortunately fixing that did not change anything. Nor did any of the suggested fixes, I still always get the 1561 error. For the C++ project I have tried building both a lib and a dll. On possible thing is the question from mecej4:
Have you configured the dependence of the Fortran project on the C++ library?
How do I do that?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Attach a ZIP of your Visual Studio solution with projects and let us see what you actually did.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thomann, Gary wrote:Thank you for all the comments. Call the wrong subroutine name from the fortran code was dumb. Unfortunately fixing that did not change anything. Nor did any of the suggested fixes, I still always get the 1561 error. For the C++ project I have tried building both a lib and a dll. On possible thing is the question from mecej4:
Have you configured the dependence of the Fortran project on the C++ library?
How do I do that?
Here, you can try the Visual Studio Solution and Microsoft C++ DLL project along with Intel Fortran Console Application project in the attached zip file.
You'll see the code is as follows:
#include <iostream> using namespace std; extern "C" { void TestAdd(float *X1, float *Y1, float *Z1); } void TestAdd(float *X1, float *Y1, float *Z1) { *Z1 = *Y1 + *X1; return; }
module first_try_Mod use, intrinsic :: iso_c_binding, only : c_float implicit none interface subroutine TestAdd( X1, Y1, Z1) bind(C, name="TestAdd") ! void TestAdd(float *X1, float *Y1, float *Z1); import :: c_float implicit none ! Argument list real(c_float), intent(inout) :: X1 real(c_float), intent(inout) :: Y1 real(c_float), intent(inout) :: Z1 end subroutine end interface end module first_try_Mod
program TryAdd use, intrinsic :: iso_c_binding, only : c_float use first_try_mod, only : TestAdd implicit none real(c_float) :: X1, Y1, Z1 x1 = 1.0_c_float y1 = 4.0_c_float z1 = 5.0_c_float call TestAdd(X1, Y1, Z1) print *, "z1 = ", z1 end program TryAdd
You can unzip to a folder, open the solution, build it (F6 key), and hit Ctrl-F5 hot key to execute to get the following:
z1 = 5.000000 Press any key to continue . . .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is a mess.
Your C++ project is building a DLL, but it exports no symbols. You have told VS that your C++ project is dependent on the Fortran project, when it should be the other way around,. The Fortran project has no "subsystem" defined - I am not sure how you managed that, but I note that the project type is "Application" and not "Console Application". I also note that the C++ project is building into the Fortran project's output folder, which is usually a bad move, as VS may delete one project's outputs before building the other project.
Start over. Create a blank Visual Studio solution. Add a Fortran Console Application and a C++ Static Library project. Add the proper sources to the respective projects. Right click the Fortran project, select Build Dependencies > Project Dependencies. Check the box for the C++ project. (This will work when the C++ project is a static library, but not when it's a DLL.
I think this should take care of it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you very much Steve. I can believe it is a mess; it is hard to learn something when you crash full speed into it. I believe it would be helpful to have more tutorial info and some examples including solution files for calling C++ from Fortran. I have certainly had a hard time with it, although that seems to happen with everything I do.
I am a consultant (and used to work for) a company that makes a large simulation program, with Fortran used for the models. I am interested to see if C++ could help with parts of the models.
Again, thank you for looking at this! I will try again.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The Intel Parallel Studio XE for Windows Samples Bundle (filter by Windows) contains examples of Fortran calling into C (with some text about differences between C and C++), as well as C calling Fortran. You may find these worth a study.
Normally, the way you get a Fortran project to link to the library from another project is to set the Project Dependencies such that the executable project is dependent on the library project. That works fine for Fortran-Fortran (and in that case also makes any compiled modules in the library project visible to the executable), and works for Fortran-C where the C/C++ project is a static library, but Microsoft broke this when the C/C++ project is a DLL - in that case you have to manually add the library to the parent project (can do it as if it were a source file, or use the Linker property pages.)
You should also study the Fortran standard's C interoperability features, which got expanded in Fortran 2018 and are fully supported by the current Intel Fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thomann, Gary wrote:.. I can believe it is a mess; it is hard to learn something when you crash full speed into it. I believe it would be helpful to have more tutorial info and some examples including solution files for calling C++ from Fortran. I have certainly had a hard time with it, although that seems to happen with everything I do.
I am a consultant (and used to work for) a company that makes a large simulation program, with Fortran used for the models. I am interested to see if C++ could help with parts of the models.
Again, thank you for looking at this! I will try again.
Will it be possible for you to take a look at Quote #11 above and try it out and provide your feedback here please?
You have a fully worked out example in Quote #11 of the very specific scenario you have presented in this thread including your own code structure and a C++ DLL and a Fortran main project.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thomann, Gary wrote:Thank you very much Steve. I can believe it is a mess; it is hard to learn something when you crash full speed into it. I believe it would be helpful to have more tutorial info and some examples including solution files for calling C++ from Fortran. I have certainly had a hard time with it, although that seems to happen with everything I do.
I am a consultant (and used to work for) a company that makes a large simulation program, with Fortran used for the models. I am interested to see if C++ could help with parts of the models.
Again, thank you for looking at this! I will try again.
Dear Gary:
This is not the place to complain about the state of the world or the fact that HAL has taken a holiday or that Heinlein was correct in his statement about non-mathematicians - if this eludes you then I am sorry.
The type of problem that you are talking about interests a very limited subset of the "known" world of computer programmers and most these programmer's days are limited to PYTHON or JAVA or some such thing. If you join this smaller limited set of programmers, here, then you are dealing with new programs and versions that are often poorly documented or not documented. You are now an Eagle Scout and you do not need to ask if I flip the Registry Entry to show the version of windows on my desktop will I open a flaw in the firewall. (I was asked that this week)
If you want an extreme example of this problem download the original AUTOLISP manual and try and write a program. Lisp's learning curve is straight up and very very hard. At that stage there was no Amazon and it took 12 weeks to get the Winston and Horn book shipped from MIT. I
The Internet gives you all the data you need - but there is no librarian -- instead there are volunteers like this forum to answer your questions to the best of their ability. I understand this group -- I am not really a part of it -- I just hope they can solve some of my problems. And i enjoy the banter
So it is best to be polite and stick to specific questions. If you understand 42 as the answer then you understand these people.
Good hunting
John
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page