Visual Studio 2019 windows console program unresolved external symbol

jjhn
jjhn used Ask the Experts™
on
I'm getting the following linker error when building a solution for a Visual Studio 2019 windows console program...

Error      LNK2001      unresolved external symbol "public: virtual void __thiscall kymeta::sensor::API::StartServiceA(void)const " (?StartServiceA@API@sensor@kymeta@@UBEXXZ)

I have no method in my code that is named 'StartServiceA'. Where is this coming from?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Dr. KlahnPrincipal Software Engineer

Commented:
Possibly you are using some code from a library which has not been included.  The inclusion of "API" in the call path would tend to confirm this.

https://docs.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-error-lnk2001?view=vs-2019

Also a common problem:  "This error can occur if your code refers to a symbol from one version of a library, but you supply a different version of the library to the linker."

Author

Commented:
I think if found the cause but am still looking for a solution.

I have two pieces of code, one an executable and the other a static lib. So I'm obviously trying to link the static lib into my executable. The static lib code does contain a namespace called 'API', but no method named 'StartServiceA' within that namespace. It does, however, contain a method named 'StartService'. If I hover over the declaration of 'StartService' in the header, VS is telling me it's a #define that expands to 'StartServiceA'. The hyperlink in VS takes me to its definition in a file called 'winsvc.h' (located in directory C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um).

This is an overridden method in my API header and I don't want to change any of the base code. How can I get VS to ignore this #define?
Not sure this will help you to ignore your #define, since I don't see the organization of your files.
#ifdef abc
    #undef abc
#endif

Open in new window

Here is a little discussion on this topic.
https://stackoverflow.com/questions/27126890/how-to-ignore-a-define-directive

But, could you just comment out the #define temporarily to verify that your code works as desired .
11/26 Forrester Webinar: Savings for Enterprise

How can your organization benefit from savings just by replacing your legacy backup solutions with Acronis' #CyberProtection? Join Forrester's Joe Branca and Ryan Davis from Acronis live as they explain how you can too.

Qlemo"Batchelor", Developer and EE Topic Advisor
Top Expert 2015

Commented:
The A suffix is there to map to a function handling "ANSI" (8bit) strings, opposed to suffix W (for "wide") handling Unicode (16bit). That mapping is done by #define as seen. You'll find that done a lot with C++ on Windows. The reference you found to winsvc.h fits into that scheme. But, don't think it should be applied to the API function. Disabling that specific define temporarily might help in getting one step further. But the real bag is IMHO that the API call is not prepared to differ between ANSI and Unicode - or it is just an inproper sequence of #include.
Alternatively, could you define a StartServiceA method in the API namespace that calls the StartService method?
Top Expert 2016

Commented:
How can I get VS to ignore this #define?

the most common method is to undef the wrong definition (like phoffric already showed) before use and to (re)define it after use.

#ifdef StartService
#define StartService_Defined 
#undef StartService
#endif

Open in new window

   

now you can call or define StartService and it is not expanded to StartServiceA

     int x = StartService(some_variable);   // it doesn't expand to StartServiceA

Open in new window


// after use
#ifdef StartService_Defined 
#define StartService StartServiceA   // restore old value
#undef StartService_Defined             // just to make it clean
#endif

Open in new window


you may put those blocks around every usage of StartService (in header or cpp),

or, in case you were sure that WINAPI function ::StartService wasn't called/needed directly or indirectly by your program, you can do the first block into the header file where your function StartService was declared/defined. put it below all other #include statements of the header.

the second block to restore the macro was not needed in this case. it doesn't harm if you do it into the source files where the StartService call was used (below last usage). however, you must not do it into a header because this would restore the old macro when including the header file.

Sara

Author

Commented:
There were a number of helpful suggestions here, some of which I expected to work, but I continue to have the same link problem. What I am trying to do is build a Linux application in a Windows environment. I know I was able to do this a couple years ago but don't remember how I got around this particular issue. I am abandoning this science project and will put my efforts into using either MinGW, cygwin or some new mechanism in VS 2019 for Linux projects (WSL possibly).

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial