MSVC未解析链接可执行文件的外部符号

时间:2011-08-11 22:22:27

标签: visual-c++ linker dependencies dllexport visual-studio-2010

我有两个现有的可执行文件A和T,在同一个解决方案中,在我触摸它们之前都运行得很好。在可执行文件中,A是定义类P的头,以及静态实例MyP的原型。定义在项目A中编译。在可执行文件T中,我想在项目A中调用MyP的成员函数,因此我将dllimport / export宏添加到类的声明和标题中的MyP(不在定义中),并且包含项目T中的标题.dllimport / export宏是标准的,A_EXPORTS在项目A中定义,但不在T中定义。

#ifdef A_EXPORTS
#define A_API __declspec(dllexport)
#else
#define A_API __declspec(dllimport)
#endif

//various definitions and includes, defining ENUM_RECORDING_TYPE and ERROR
A_API HFILE viosopen(const _TCHAR *path, ENUM_RECORDING_TYPE rt, int flags);
A_API struct P { 
    ERROR B(SHORT phraseNum);
};
A_API extern P MyP;

我在解决方案中添加了项目A作为项目T的依赖项。 A仍然可以编译,但是T为函数调用提供unresolved external symbol "__declspec(import) <snip> referenced in function <snip>,为静态对象提供unresolved external symbol "__declspec(dllimport) class P MyP" <snip>。我也在输出日志中看到它开始链接之后:Creating library Debug/A.lib and object Debug/A.exp这似乎是不祥的,因为它应该链接到现有的可执行文件。

我的问题是:我如何告诉MSVC 2010它们在哪里?我认为简单地将A设置为依赖关系会让它自动计算出来。我可以链接现有的可执行文件,对吗?

2 个答案:

答案 0 :(得分:2)

静态链接您的程序,您不需要__declspec()内容,并且您不需要单独的项目来创建LIB文件。我想您可以使用A项目中的.obj文件进行链接。

你的A项目有一个头文件,可能有一个.cpp文件,其中包含该头文件中描述的项目的实现。假设您的头文件是foo.h,相关的实现是foo.cpp。编译时,foo.obj<solutiondir>\A\Debug中间文件夹中应该有<solutiondir>\A\release个中间文件。该文件可以由链接器使用。

在项目T的属性中,找到Linker |输入并更改“Additional Dependencies”属性以包含foo.obj文件。一种方法是使用相对文件路径来定位文件 - 例如,在调试配置中..\A\Debug\foo.obj。另一种方法是在“附加依赖项”中使用简单文件名 - foo.obj - 然后使用链接器|一般|其他库目录“以帮助链接器查找文件 - 例如..\A\$(IntDir)。使用$(IntDir)宏的优点是相同的值适用于调试和发布设置。

请记住从T项目到A项目建立构建依赖项,以确保首先编译A项目。否则,当T链接器查找时,foo.obj文件可能不存在。在Solution属性中,选择Project Dependencies,然后将Project T设置为依赖于Project A.

动态链接,您需要使用A.LIB文件,如@ajay所说。 __declspec(DllImport)告诉编译器您要导入哪些函数和数据但不告诉它从哪里导入这些东西。

使用A.LIB文件作为链接器的输入与在静态链接情况下使用foo.obj文件非常相似,只是lib文件最终位于解决方案输出目录{{1}中而不是项目中间目录<solutiondir>\Debug

创建和使用DLL的walkthrough可能是有用的背景。

答案 1 :(得分:0)

我认为项目A是DLL而不是EXE,它成功生成了一个LIB文件。 您需要在项目B中使用A.LIB作为链接器输入。只是生成LIB文件不会使其他项目自动链接到它。