Reputation: 728
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:
#include "Gvar.h"
with #pragma managed(push, off)
and #pragma managed(pop)
Upvotes: 0
Views: 2051
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