Fortran and C++: Linking error in Visual Studio - c++

System: Windows-7-64-bit/Visual-Studio-2010/Intel-Visual-Fortran-11.
I am creating 32-bit executables.
Fortran routine declaration
SUBROUTINE LA01BD(N,M,L,A,B,C,X,F,IA,IPRINT,IND,WK,IER)
!DEC$ ATTRIBUTES DLLEXPORT::LA01BD
!DEC$ ATTRIBUTES STDCALL,REFERENCE,ALIAS:"LA01BD"::LA01BD
use, intrinsic :: ISO_C_BINDING
C++ function signature declaration
extern "C" {void __stdcall LA01BD(int *N, int *M, int *L, double *A, double *B, double *C, double *X, double *F, int *IA, int *IPRINT, int *IND, double *WK, int *IER); }
I created the dll from fortran code using Visual Studio 2010 and Intel Visual Fortran compiler 11. I checked the exported symobol in dependency walker and the Function is "LA01BD".
When using the same dll (the .lib file during linking) in my C++ project, I get the following linker error.
lpwrap.obj : error LNK2001: unresolved external symbol _LA01BD#52
I am unable to resolve this issue. What does suffix "#52" does? How to fix the linking issue?
Thanks.

The C++ compiler applies name decoration to the identifier. The __stdcall decoration is a leading _underscore and a trailing #n where n is the size of the activation frame.
The ALIAS directive in your Fortran code caused this problem, you forced it to be exported as "LA01BD" instead of "_LA01BD#52". You should first try to remove it so the normal name decoration is applied. If that's not an option then you'll need to either create an import library with lib.exe /def from a properly crafted .def file or fallback to late binding with GetProcAddress().

If you must use the STDCALL calling convention, then add the DECORATE attribute to the Fortran side to instruct the compiler to decorate the specified alias.
SUBROUTINE LA01BD(N,M,L,A,B,C,X,F,IA,IPRINT,IND,WK,IER)
!DEC$ ATTRIBUTES DLLEXPORT::LA01BD
!DEC$ ATTRIBUTES STDCALL,REFERENCE,ALIAS:"LA01BD"::LA01BD
!DEC$ ATTRIBUTES DECORATE :: LA01BD

it is caused by name mangling, please ref this for details. I guess you missed the extern "c" in your C++ project.

Related

Decorated name for function generated improperly

I'm trying to compile some third party C++ code into my 32-bit C++ application with Visual Studio 2017 (upgrading from Visual Studio 6.0). I have .h files and a .lib file from the third party. The linker is finding the library, but it is not finding the decorated names contained within. It appears to be because the compiler is replacing "__int8" with "char".
The linker error is:
LNK2019 unresolved external symbol "signed char __cdecl Check_The_Thing(void)" (?Check_The_Thing##YACXZ) referenced in function (redacted)
The function is defined in the .h:
_declspec(dllexport) API_RETURN_TYPE Check_The_Thing ( void );
API_RETURN_TYPE is defined in the .h:
_declspec(dllimport) typedef signed __int8 int_8;
_declspec(dllimport) typedef int_8 API_RETURN_TYPE;
Using dumpbin /exports, I can see that my lib and associated dll exports Check_The_Thing:
?Check_The_Thing##YA_DXZ (__int8 __cdecl Check_The_Thing(void))
Using undname, I can see that the decorated name in the lib evaulates properly:
Undecoration of :- "?Check_The_Thing##YA_DXZ"
is :- "__int8 __cdecl Check_The_Thing(void)"
But the compiler-generated decorated name does NOT evaluate properly (based on the code):
Undecoration of :- "?Check_The_Thing##YACXZ"
is :- "signed char __cdecl Check_The_Thing(void)"
According to https://en.wikiversity.org/wiki/Visual_C%2B%2B_name_mangling, the "C" in YACXZ evaluates to "signed char" and the "_D" evaluates to "__int8". What I can't figure out is why the compiler is interpreting API_RETURN_TYPE as "char" instead of "__int8". It's clear that the lib/dll exports should have "_C" instead of "_D" given that API_RETURN_TYPE is a "signed __int8" not just "__int8".
I've fiddled with a bunch of the compiler settings with no luck. As suggested here (Cannot find decorated function name in dll) , I made sure I was using MBCS instead of Unicode (it was unset before), but that also made no difference.
Specifically defining API_RETURN_TYPE as __int8 makes no difference except to change the "C" to a "D" (progress!) and likewise undname shows the return type as "char" instead of "signed char". Changing the function definition's return type to __int8 has the same effect as changing API_RETURN_TYPE.
So, my question: How can I force the compiler to properly define my exports with "__int8" (or "_D") instead of char ("D")?
Side note: the linker error is the same for the cases where __int16, __int32, and __int64 are used.
EDIT: Actually, the library defines __int64 types but I'm not using any. There aren't any __int64 linker errors.
At least since Visual Studio 2003 (!), "The __int8 data type is synonymous with type char".
Obviously, the compiler can't have different name mangling for two ways to name the same type.
Also insightful is this page which shows that __int8 is (signed) char but __int64 is not long long; the latter are merely equivalent.

How to wrap a C __cdecl API so that FORTRAN can call it (using __stdcall)?

I'm working with a third party C library that is using the default (__cdecl) calling convention and I need to be able to call the third party library from FORTRAN. FORTRAN's default calling convention is __stdcall and so I've written a basic wrapper in C++
int __stdcall wrapper_sub(char* ver, int* days)
{
return original_sub(ver,days);
};
with function prototype
int __stdcall wrapper_sub(char*, int*);
I'm able to compile without errors but when I check the symbol table of the wrapper library I get
?wrapper_sub##YAHOADPAH#Z(int __cdecl original_sub(char *, int *))
It would seem that the linker is not finding original_sub and the process is failing silently. I've included all necessary references and directories into the project so that the wrapper solution should correctly resolve the third party API.
The FORTRAN call is made as follows
PROGRAM MAIN
IMPLICIT REAL*8 (A-H, O-Z)
CHARACTER*(4) VER
VER = '1.0'
ISTAT = wrapper_sub(VER,IDAYS)
STOP
END
after including an external reference to the wrapper library, I get the following error
error LNK2001: unresolved external symbol _WRAPPER_SUB#12
Is there something I'm missing? or is there a another (less error prone?) way to wrap the C API so that I can call it from FORTRAN?
The linker can't link your FORTRAN code to the library because the function name is mangled ( C++ thinks the function is named ?wrapper_sub##YAHOADPAH#Z, FORTRAN is expecting it to be named wrapper_sub)
Write your wrapper in C, not C++, or add an extern "C" to fix the problem.
extern "C" int __stdcall wrapper_sub(char* ver, int* days)
See this SO question for more details: In C++ source, what is the effect of extern "C"?

How to disable C++ 7.1 Name mangling? :(

I have a library code which is written in VS 2003 , C++ 7.1
I managed to compile it in VS 2010. Now i need to compile it in VS2003 as well.
Problem is that i can not prevent VS2003 name mangling !
I used __declspec(dllexport) __stdcall before function name and i also put codes in extern "C" block.
I still get mangled function names when i compile it in VS 20003. I dont need a .def file when i use __declspec(dllexport) right?
hee is the code :
extern "C"
{
void __declspec(dllexport) __stdcall FreeMyObject(MyObjectHandle pObj)
{
delete pObj;
}
}
Also "Callin Convention" is __cdecl (/Gd)
Why i get mangled function names? is there any options i need to set in compiler option?
The keyword _stdcall, along with _cdecl, _thiscall, and others, are all calling conventions specifying how the compiler handles pushing and popping the arguments and the return value. Functions names made with _stdcall (at least in visual studio) are "decorated" when they are exported. If you want to find the exported name of the function, you can use the visual studio command line function DUMPBIN /EXPORTS "DLL file location". Your function name will probably look something like this: _FreeMyObject#(some number). You could also use a .def file and define the name yourself, but I personally think that is a pain.

fatal error LNK1127: library is corrupt --> after adding extern "C" to function prototype

I have an external library made using C code. I wish to call a function from the library in my c++ project. The original format of the function prototype was.
extern void butterThreeBp(real_T eml_dt, real_T eml_fl, real_T eml_fu, real_T eml_b3[7], real_T eml_a3[7]);
And this caused the following linker error in MSVC2008
error LNK2019: unresolved external symbol "void __cdecl butterThreeBp(double,double,double,double * const,double * const)" (?butterThreeBp##YAXNNNQAN0#Z) referenced in function "public: void __thiscall myThread::setDRNLc(double)" (?setDRNLc#myThread##QAEXN#Z)
I then changed this prototype to
extern "C" void ...
and then get the following error:
\butterThreeBp.lib : fatal error LNK1127: library is corrupt
I have rebuilt the library numerous times and am pretty certain that it is not corrupt. Any help would be great. Thanks!!
You do not have to use the included LCC compiler with MATLAB. The simplest solution is to get MATLAB to use VC++. http://www.mathworks.com/support/compilers/R2010b/index.html
IIRC you should add extern "C" only when compiling with C++ compiler.
Something like that:
#ifdef __cplusplus
extern "C" {
#endif
// the declarations
#ifdef __cplusplus
}
#endif
Got it! I generated the library code using the MATLAB embedded coder and was using Matlab's Lcc built in compiler to build the library. I am working on the main application in MSVC, therefore I guess there must have been some calling convention problem between the library (Lcc) and my main project (MSVC). This problem was particularly difficult to spot because one of my libraries (ButterOneLp) worked fine, even though it was generated using Lcc. However, another library did not work.
The problem was fixed by using the
mex -setup
. . . command in MATLAB and changing the default compiler to MSVC as opposed to the default Lcc.
I think that Lcc is based on gcc, so if anybody knows how to change the calling convention in the C++ code so that gcc/lcc libraries can be called from MSVC, that would be great. However, that is a whole different question to the original on posted.
The moral of this story is to check that your library and calling application are/were built using the same compiler if you get a "fatal error LNK1127: library is corrupt".

Mixed calling conventions make compilation errors

I have a library (C++) which has some API functions. One of them is declared as __cdecl, but gets a function poiner from __stdcall. Something like:
typedef int (__stdcall *Func)(unsigned char* buffer);
//...
int ApiFunc(Func funcPtr); //This is __cdecl since it is an 'extern "C"' library and the calling convention is not specified
Then - I have a C++ executable project which uses this library, but doesn't call the above API or uses the Func type.
After changing the calling convention of Func to __stdcall, I get the following compilation error:
error C2995:
'std::pointer_to_unary_function<_Arg,_Result,_Result(__cdecl *)(_Arg)> std::ptr_fun(_Result (__cdecl *)(_Arg))' : function
template has already been
defined c:\program files\microsoft
visual studio 8\vc\include\functional
Any idea what could it be?
Thanks in advance!!
Err.. they're incompatible. You have to specify the same calling convention on both sides of the call. Otherwise attempting to call will blow up the machine stack.
They ARE compatible, in Windows at least (and in Linux there isn't __stdcall at all...)
The problem was that by mistake, the library re-defined __stdcall for compatibility with Linux, as:
#ifndef __MYLIB_WIN32
//Just an empty define for Linux compilation
#define __stdcall
#endif
The exe project includes this definition, and __MYLIB_WIN32 was not defined in it, but in the library only.
Changing the above definition to:
#ifndef WIN32
//Just an empty define for Linux compilation
#define __stdcall
#endif
and everything works fine.
Thank you all.