尽管选项正确,但静态链接不能用于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.h
内extern C
。
#include "stdafx.h"
#include "Wrapper.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "gvar.h"
#ifdef __cplusplus
}
#endif
...
//other code in wrapper.cpp
原因是名称重整方案C
和C++
是不同的。因此,在编译/链接C++代码时,C
代码库中定义的变量名称与链接器搜索的代码不同。
This works ..谢谢!但是我认为如果C代码是用C编译器编译的,然后通过C++链接器链接的话,那么名称修改只是一个问题?而在我的情况下,静态库是用VS2010 C++编译器编译的,据我所知... – 9a3eedi 2015-02-10 05:30:13
@ 9a3eedi,VS2010将根据C编译器编译C代码,并将使用名称修改方案,对于C++代码也类似。所以当你把它们结合起来的时候 - 没有'extern c ..'你有问题。 – Rohan 2015-02-10 05:38:30
我明白了,但是如果相同的代码也被认为是有效的C++,那么VS2010如何认识到C代码应该被视为C?它看看文件扩展名吗? – 9a3eedi 2015-02-10 05:49:33