Decorated name for function generated improperly

725 Views Asked by At

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.

1

There are 1 best solutions below

3
On

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.