9a3eedi
9a3eedi

Reputation: 728

Static linking does not work with C++/CLI (unresolved external symbol) despite correct options

I have 2 projects: a native C project, and a C++/CLI wrapper which will be used to allow the C project to interop with a C# program. Both projects are located in the same Visual Studio 2010 solution. In order to allow for interop, I was planning to have the C++/CLI wrapper statically link with the native C project, so that I can access its global variables and functions, and have both the wrapper and the native C project compile into one loadable DLL.

For my C project, I've set the project configuration type to "static library", and with no CLR support. From what I've seen, it builds only to a .lib file, with no DLL. Because VS2010 uses a C++ compiler, I suppose the code is being compiled as C++, which is fine by me.

I've used the C++/CLI wizard to create the second project, and then I added the name of the library in the linker options and its directory. If I understand correctly this should make the linker link the static library with the C++/CLI DLL. I also added the native C project as a reference to the C++/CLI wrapper project (in Frameworks and References)

To test this, I tried using a global variable from the C project in my C++/CLI .cpp file. This is my code (with unrelated stuff removed (at least, I hope they're unrelated)):

Wrapper.cpp (located in C++/CLI wrapper project)

#include "stdafx.h"

#include "Wrapper.h"
#include "Gvar.h"

Wrapper::Wrapper()
{
}

Wrapper::~Wrapper()
{
}

Wrapper::!Wrapper()
{
}

void Wrapper::initialize(int year)
{
    g_year = year
    System::Console::WriteLine(::g_year);
}

Gvar.h (located in static library project)

#ifndef GVAR_H
#define GVAR_H

extern int g_year;

#endif

Gvar.c (located in static library project)

#include "Gvar.h"

int g_year = 2013;

When I build the C++/CLI project, I get the following linker error:

2>Wrapper.obj : error LNK2020: unresolved token (0A00003B) "int g_year" (?g_year@@3HA)
2>Wrapper.obj : error LNK2001: unresolved external symbol "int g_year" (?g_year@@3HA)

I'm not sure what I'm doing wrong. I clearly defined the variable in the C file.

I also know that the linker actually looks at the library I specified, because after enabling "show progress" in the linker options I can see that the linker searches inside the library, but it seems it's not finding anything:

(a small snippet of the output):

...
2>  
2>  Finished searching libraries
2>  Search transition ?g_year@@3HA->__t2m@?g_year@@3HA
2>  Search transition __pRawDllMain->__t2m@__pRawDllMain
2>  Merging metadata
2>  Finished merging metadata
2>  
2>  Searching libraries
2>      Searching C:\Users\9a3eedi\Documents\Solution\Static Lib\Debug\Static Lib.lib:
2>      Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\MSVCRTD.lib:
2>      Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\OLDNAMES.lib:
2>      Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\MSVCMRTD.lib:
2>      Searching C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\lib\MSCOREE.lib:
2>        Found __CorDllMain@12
2>          Loaded MSCOREE.lib(mscoree.dll)
2>        Found __IMPORT_DESCRIPTOR_mscoree
2>          Referenced in MSCOREE.lib(mscoree.dll)
2>          Loaded MSCOREE.lib(mscoree.dll)
2>        Found mscoree_NULL_THUNK_DATA
2>          Referenced in MSCOREE.lib(mscoree.dll)
2>          Loaded MSCOREE.lib(mscoree.dll)
2>      Searching C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\lib\kernel32.lib:
2>      Searching C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\lib\uuid.lib:
2>      Searching C:\Users\9a3eedi\Documents\Solution\Static Lib\Debug\Static Lib.lib:
2>      Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\MSVCRTD.lib:
2>      Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\OLDNAMES.lib:
2>      Searching C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\MSVCMRTD.lib:
2>  
2>  Finished searching libraries
2>  Generating clr ijw/native image
2>  
2>  Searching libraries
2>      Searching C:\Users\9a3eedi\Documents\Solution\Static Lib\Debug\Static Lib.lib:
...

The static library in question is "Static Lib.lib". It's in the linker output above.

Why isn't the linker able to resolve my global variable?

I have tried the following after some googling, but none of them do anything or make any difference:

Upvotes: 0

Views: 2051

Answers (1)

Rohan
Rohan

Reputation: 53316

Update your wrapper.cpp to include the gvar.h within extern C.

#include "stdafx.h"
#include "Wrapper.h"

#ifdef __cplusplus 
extern "C" {
#endif

#include "gvar.h"

#ifdef __cplusplus
}
#endif

...
//other code in wrapper.cpp

The cause is name mangling scheme in C and C++ are different. So the variable name defined in library of C code will not be same as the one searched by linker while compiling/linking C++ code.

More reference at In C++ source, what is the effect of extern "C"?

Upvotes: 1

Related Questions