尽管选项正确,但静态链接不能用于C++/CLI(无法解析的外部符号)

问题描述:

我有2个项目:一个本地C项目和一个C++/CLI包装器,它将用于允许C项目与C#程序。这两个项目都位于相同的Visual Studio 2010解决方案中。为了允许互操作,我打算让C++/CLI包装器与本地C项目静态链接,以便我可以访问其全局变量和函数,并且将包装器和本地C项目编译为一个可加载DLL。尽管选项正确,但静态链接不能用于C++/CLI(无法解析的外部符号)

对于我的C项目,我已经将项目配置类型设置为“静态库”,并且没有CLR支持。从我所看到的,它只生成一个.lib文件,没有DLL。由于VS2010使用C++编译器,我想代码正在编译为C++,这对我来说很好。

我已经使用C++/CLI向导来创建第二个项目,然后我在链接器选项及其目录中添加了库的名称。如果我理解正确,这应该使链接器将静态库链接到C++/CLI DLL。我还将本地C项目添加为C++/CLI包装器项目的引用(在框架和参考中)

为了测试这个,我尝试在C++/CLI .cpp文件中使用来自C项目的全局变量。这是我的代码(与无关的东西去掉(,我希望至少他们是不相关的)):

Wrapper.cpp(位于C++/CLI包装项目)

#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(位于在静态库项目)

#ifndef GVAR_H 
#define GVAR_H 

extern int g_year; 

#endif 

Gvar.c(位于静态库项目)

#include "Gvar.h" 

int g_year = 2013; 

当我BUIL d的C++/CLI的项目,我得到下面的连接错误:

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

我不知道我在做什么错。我明确定义了C文件中的变量。

我也知道,连接器实际上看起来在我指定的库,因为能够在连接选项“显示进度”我看到后,库里面的链接的搜索,但似乎它没有找到任何东西:

(输出的一小片断):

... 
2> 
2> Finished searching libraries 
2> Search transition [email protected]@3HA->[email protected][email protected]@3HA 
2> Search transition __pRawDllMain->[email protected]__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 [email protected] 
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: 
... 

在考虑中的静态库是 “静态Lib.lib”。它在上面的链接器输出中。

为什么链接器不能解析我的全局变量?

我已经尝试了一些谷歌上搜索后下,但他们没有做任何事或任何区别:

  • 添加的#pragma评论(LIB,“静态Lib.lib”)来包装。CPP
  • 周围的#include "Gvar.h"#pragma managed(push, off)#pragma managed(pop)
  • 上述两个

更新您的wrapper.cpp到包括gvar.hextern C

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

#ifdef __cplusplus 
extern "C" { 
#endif 

#include "gvar.h" 

#ifdef __cplusplus 
} 
#endif 

... 
//other code in wrapper.cpp 

原因是名称重整方案CC++是不同的。因此,在编译/链接C++代码时,C代码库中定义的变量名称与链接器搜索的代码不同。

更多参考In C++ source, what is the effect of extern "C"?

+0

This works ..谢谢!但是我认为如果C代码是用C编译器编译的,然后通过C++链接器链接的话,那么名称修改只是一个问题?而在我的情况下,静态库是用VS2010 C++编译器编译的,据我所知... – 9a3eedi 2015-02-10 05:30:13

+1

@ 9a3eedi,VS2010将根据C编译器编译C代码,并将使用名称修改方案,对于C++代码也类似。所以当你把它们结合起来的时候 - 没有'extern c ..'你有问题。 – Rohan 2015-02-10 05:38:30

+0

我明白了,但是如果相同的代码也被认为是有效的C++,那么VS2010如何认识到C代码应该被视为C?它看看文件扩展名吗? – 9a3eedi 2015-02-10 05:49:33