Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Intel Oneapi fortran and C++

Blake1
Beginner
786 Views

I have vs2019 installed and running. And, yes, I can compile and run a simple "Hello World" program with it. I recently downloaded oneAPI as Microsoft doesn't support fortran and the package I am trying to migrate to windows 10 has a mix of fortran and C++. I can get everything to compile, but when VS2019 tries to link, it can not resolve the reference to the fortran entry point in the C++ code. I have determined that the object code with the call has the name of the routine being called followed by a "@0". In the corresponding fortran code, the same routine, in the fortran object has the call, but not followed by "@0". I have tried everything I can find to resolve the issue, but nothing seems to work. Is there a simple fix for this? On the other hand, maybe OneAPI for both the fortran and C++ would be a better mix. I only downloaded one version, so both should be the same version.

 

                                                           Blake Mitchell

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
776 Views

The @0 indicates that this is a 32-bit routine with the STDCALL calling convention. On 32-bit Windows, there are two calling conventions, STDCALL (primarily used by Visual Basic/Excel and Windows API routines) and C. (64-bit Windows has only one convention.) The number after the @ indicates the number of bytes taken up by the argument list pushed onto the stack. With STDCALL, the called routine pops the argument list off the stack with a RET instruction, and this requires that it know how much to pop. To avoid mismatches here, the naming convention decorates the global name with the number of bytes to pop. (The C convention has the calling routine do the pop, which takes an extra instruction, but it knows what it pushed.)

While both Intel Fortran and Microsoft C++ default to the C convention, there are pragmas/attributes for both compilers that let you select STDCALL if needed. It would appear that your C++ routines were built to use STDCALL.  There are various ways of resolving the difference, but I'd suggest modifying the Fortran code to tell it that these specific routines are STDCALL.  How many routines are we talking about here? How does the Fortran code declare the C++ routine it wants to call? Show the declaration(s) here and I'll give you the fixes.

View solution in original post

2 Replies
Steve_Lionel
Honored Contributor III
777 Views

The @0 indicates that this is a 32-bit routine with the STDCALL calling convention. On 32-bit Windows, there are two calling conventions, STDCALL (primarily used by Visual Basic/Excel and Windows API routines) and C. (64-bit Windows has only one convention.) The number after the @ indicates the number of bytes taken up by the argument list pushed onto the stack. With STDCALL, the called routine pops the argument list off the stack with a RET instruction, and this requires that it know how much to pop. To avoid mismatches here, the naming convention decorates the global name with the number of bytes to pop. (The C convention has the calling routine do the pop, which takes an extra instruction, but it knows what it pushed.)

While both Intel Fortran and Microsoft C++ default to the C convention, there are pragmas/attributes for both compilers that let you select STDCALL if needed. It would appear that your C++ routines were built to use STDCALL.  There are various ways of resolving the difference, but I'd suggest modifying the Fortran code to tell it that these specific routines are STDCALL.  How many routines are we talking about here? How does the Fortran code declare the C++ routine it wants to call? Show the declaration(s) here and I'll give you the fixes.

Blake1
Beginner
685 Views

Hi Steve,

Yeah, thanks for the info. That really did the trick. Now I have a new issue that I ran into as a result of the fact

that most of the original unresolved external issues I had are now resolved. What I was not expecting was that the code, in the library I am using, had some additional unresolved external issues. I decided to take a look at the source for the named files. Well, because both Intel and Microsoft do what ever they darn well please with YOUR files, I could not locate the correct source code. Okay, so I am going to scrap the project I used to build the static library and see if I can nail down some type of naming scheme so I don't lose track of them again. Now for the problem. In the meantime, I decided to go back and run a build on what might be called the 'main' C++ project to make sure I could reproduce the previous errors. I have had no luck doing so. All kinds of new errors have suddenly arisen from code I had killed because it didn't belong in the project. For some reason, it came back like zombies rising from the grave. I killed them all off again, including the hidden X.o files to get rid of those error. But now, I get a bunch more new errors as it is saying the all of the libraries we use with the project are no good because they contain 32 bit code while the target machine is 64 bit. This has got to be the dumbest thing I have ever seen. Someone should tell Intel that 32 bit code will work just fine on a 64 bit machine, but you should not be able run 64 bit code on a 32 bit machine. They seem to have it completely backwards! I have not been able to figure out how to tell the IDE that I want the target machine to be 32 bit. I have to do this as we do not seem to have the original source code from which the libraries were built. Google seems to want to constantly revert back to Visual Studio, in general, and nothing it talks about applies real well for me. I am still running Oneapi in conjunction with Visual Studio 2019. Is there a good way to tell the project the target machine should be 32 bit without having to scrap the C++ project and start over again?

0 Kudos
Reply