1

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.

Community
  • 1
  • 1
philselmer
  • 751
  • 4
  • 22

1 Answers1

0

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.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thanks for the reply. This is the information that I found, too. I would have thought the linker would match "_D" to "D" if it's synonymous, though. Maybe only the compiler behaves that way. – philselmer May 15 '17 at 12:24
  • @philselmer: That doesn't really make sense: since they're synonyms, there can only be name mangling. Just like `long int` and `long` are two synonyms for one type, and therefore are mangled the same. However, there is no reason to assume that VS6 uses the same name mangling as VS2017. – MSalters May 15 '17 at 12:48
  • What the compiler is doing is telling the linker that "_D" and "D" are the same, so it's going to use "D". But the linker is finding "_D" and not understanding that it's the same as "D". If MS is going to make the compiler generate the same mangled names for __int8 and char, the linker should understand the mangled names for both. EDIT: I guess I'm being unreasonable to expect VS2003 and up to understand _D because they no longer generate that. – philselmer May 15 '17 at 14:46