1

I have inherited a legacy project which utilizes some external functions from a *.lib. From what I was told, the syntax for using the *.lib was correct and this was buildable in whatever visual studio version they used. (ie, there is an extern "C" prototype file, and all the function signatures are correct).

When building, I get "error LNK2019: unresolved external symbol _A86_ReadConfigReg@12 referenced in function ..."

I'm pretty confident that this is related to the *.lib file since the *.lib file has "A86" in the name...There is also a *.dll with the same name.

I went to project properties -> Linker -> Input and listed the *.lib file name in "Additional Dependencies", but no luck. I tried adding the include directories, copying the *.lib & *.dll to the executable location. But no luck.

How do I go about fixing this error?

user2913869
  • 481
  • 2
  • 5
  • 23

1 Answers1

5

First thing you should do is inspect the library to make sure the referenced function is there. Start an msvc developer command prompt, and run dumpbin.exe

Syntax:

dumpbin /exports <full path library name>

This will give you a listing of all exported symbols from the library.

You'll get a clearer idea of what to do from there.

[EDIT]

dumpbin told you that your lib exports a function called A86_ReadConfigReg, which is a __cdecl signature and not a __stdcall signature like _A86_ReadConfigReg@12 that your linker expects.... At least two things you should do/check in order of priority.

  1. Your linker is looking for a pascal call signature and this is very odd. Does your project have __stdcall as a default for function calls? That's controlled by the /Gz switch in Project Properties->C/C++->Advanced->Calling Convention. Default should be set to __cdecl (/Gd)

  2. You should check that your include files enclose all the function declarations in an extern "C" { } block. If they don't, you can place the block around the #include directive, so you do not have to modify the library's files.

Like so:

extern "C" {
#include <mylib.h>
}
Michaël Roy
  • 6,338
  • 1
  • 15
  • 19
  • I did do this, and the output from dump bin has a line showing: "15 A86_ReadConfigReg". What is the next step? – user2913869 Jul 20 '17 at 13:07
  • @user2913869 Check updated answer for your linker issue. – Michaël Roy Jul 20 '17 at 13:32
  • The calling convention was indeed set to __cdecl (/Gd). Like I mentioned in the original question, the header file does indeed have "extern "C" { } and all the function prototypes listed between the parenthesis. I do see that the prototype is defined in this way: int _stdcall A86_ReadConfigReg (int iHandle, DWORD dwOffset, DWORD* pdwResult); So I also tried changing the "_stdcall" label to "__cdecl", and then removed it completely, but it still would not build. – user2913869 Jul 20 '17 at 13:45
  • Well, it's not normal. It looks like your headers do not match what's in the library. The missing leading _ and @12 are a very strong indicators that that RegConfigReg was compiled with __cdecl, yet the headers defines the function with an explicit __stdcall . It is almost certain that these headers were not the ones used to compile this library. Unless... Is that library written in PASCAL? – Michaël Roy Jul 20 '17 at 14:01
  • Unfortunately the library files were provided by a 3rd party, so I have no visibility into how they were generated. I can hunt around for different versions of the same library files. Is there anything that can be done at this point to make it work? I also have a *.dll with the exact same file name. Is it possible that I need to use the *.dll instead of the *.lib? – user2913869 Jul 20 '17 at 14:13
  • Sure, that's a definite possibility!!!. dumpbin works on dll's as well. It is also much easier to 'hack' the imports/exports table for dlls than for static libraries, if it ever comes to that... But looking for a different version of the lib / sources is the best you can do at the moment. – Michaël Roy Jul 20 '17 at 14:20
  • `extern "C" ` only suppresses C++ name-mangling, not the OP's problem. Calling convention mismatches are tricky when the OP did not give anything to look at, clearly you'll need to advise him using a telephone. – Hans Passant Jul 20 '17 at 16:00
  • Yes I know... There's no way this static library is going to work for him in the current state. I think he's got a better shot with the dll and possibly a linker def file, if the names don't follow the usual __stdcall convention. – Michaël Roy Jul 20 '17 at 16:07
  • Is there anything that needs to change to use the *.dll? I just change Linker-> Input to point to the DLL file, then put the *.dll into the same directory as the executable? Or are there code changes required? – user2913869 Jul 20 '17 at 17:44
  • You need to create an import library for your dll, and use that for linking. https://msdn.microsoft.com/en-us/library/0b9xe492.aspx – Michaël Roy Jul 20 '17 at 19:37