1

我有两个现有的可执行文件 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 仍然可以正常编译,但 Tunresolved 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 设置为依赖项就会让它自动解决。我可以链接到现有的可执行文件,对吧?

4

2 回答 2

2

静态链接您的程序,您不需要 __declspec() 东西,也不需要单独的项目来创建 LIB 文件。我认为您可以使用 A 项目中的 .obj 文件进行链接。

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

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

请记住设置从 T 项目到 A 项目的构建依赖项,以确保首先编译 A 项目。否则,foo.obj当 T 链接器来查找文件时,该文件可能不存在。在解决方案属性中,选择项目依赖项,然后设置项目 T 依赖于项目 A。

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

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

这个关于创建和使用 DLL 的演练可能是有用的背景。

于 2011-08-12T20:56:18.417 回答
0

我假设项目 A 是 DLL 而不是 EXE,它正在成功生成 LIB 文件。您需要A.LIB在项目 B 中使用 as Linker Input。仅生成 LIB 文件不会使其他项目自动链接到它。

于 2011-08-12T08:14:14.913 回答