MSVC 无法解析链接可执行文件的外部符号
我有两个现有的可执行文件 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 为函数调用提供了未解析的外部符号“__declspec(import)
未解析的外部符号“__declspec (dllimport) class P MyP"
用于静态对象。我还在输出日志中看到,就在它开始链接之后: 创建库 Debug/A.lib 和对象 Debug/A.exp
这似乎是不祥的,因为它应该链接到现有的可执行文件
我的问题是:我如何告诉 MSVC 2010 我在哪里?我认为简单地将 A 设置为依赖项就会自动发现我可以链接到现有的可执行文件,对吧?
I have two existing executables A and T, in the same solution that both ran just fine before I touched them. In executable A is a header defining a class P, and a prototype for a static instance MyP. The definitions are compiled in project A. In executable T, I wanted to call member functions of MyP in project A, so I added dllimport/export macros to the declarations of the class and MyP in the headers (not at the definitions), and included the headers in project T. The dllimport/export macros are standard, and A_EXPORTS is defined in project A, but not in 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;
I added project A as a dependency on project T in the solution. A still compiles fine, but T comes up with unresolved external symbol "__declspec(import) <snip> referenced in function <snip>
for the function calls, and unresolved external symbol "__declspec(dllimport) class P MyP" <snip>
for the static object. I also see in the output log, right after it starts linking: Creating library Debug/A.lib and object Debug/A.exp
which seems ominous since it's supposed to be linking against the existing executable.
My question is: how can I tell MSVC 2010 where those are? I thought simply setting A as a dependency would have it figure that out automatically. I can link against the existing executable, right?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要静态链接您的程序,您不需要 __declspec() 内容,也不需要单独的项目来创建 LIB 文件。我认为您可以使用 A 项目中的 .obj 文件进行链接。
您的 A 项目有一个头文件,并且可能有一个 .cpp 文件,其中包含该头文件中描述的项目的实现。假设您的头文件是 foo.h,关联的实现是 foo.cpp。编译后,
\A\Debug
或\A\release
中应该有一个foo.obj
中间文件代码>中间文件夹。该文件可供链接器使用。在项目 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 文件最终位于解决方案输出目录\Debug
而不是项目中间文件中目录\A\Debug
。此演练介绍了如何创建和使用DLL 可能是有用的背景。
To statically link your program you don't need the __declspec() stuff and you don't need a separate project to create a LIB file. I think you can just link using the .obj file from your A project.
Your A project has a header file and presumably has a .cpp file that contains the implementation of the items described in that header. Let's say your header file is
foo.h
and the associated implementation isfoo.cpp
. When compiled, there should be afoo.obj
intermediate file in the<solutiondir>\A\Debug
or<solutiondir>\A\release
intermediate folder. That file can be used by the linker.In project T's properties, find Linker | Input and change the "Additional Dependencies" property to include the
foo.obj
file. One approach would be to use a relative file path to locate the file - for example..\A\Debug\foo.obj
in your debug configuration. Another approach is to use the simple file name in "Additional Dependencies" -foo.obj
- and then use Linker | General | Additional Library Directories" to help the linker find the file - e.g.,..\A\$(IntDir)
. Using the$(IntDir)
macro has the advantage that the same value works for Debug and Release settings.Remember to set up a build dependency from your T project to your A project to be sure the A project is compiled first. Otherwise the
foo.obj
file might not exist when the T linker comes to look for it. In the Solution properties, select Project Dependencies and then set Project T depends on Project A.To dynamically link you need to use the
A.LIB
file as @ajay said. The__declspec(DllImport)
tells the compiler what functions and data you are importing but doesn't tell it where you are importing those things from.Using the
A.LIB
file as input to the linker is much the same as using thefoo.obj
file in the statically linking case except that the lib file ends up in the solution output directory<solutiondir>\Debug
instead of the project intermediate directory<solutiondir>\A\Debug
.This walkthrough on creating and using a DLL might be useful background.
我假设项目 A 是 DLL 而不是 EXE,它已成功生成 LIB 文件。
您需要使用
A.LIB
作为项目B中的链接器输入。仅生成LIB文件不会使其他项目自动链接到它。I asssume project A is DLL not an EXE, which is successfully producing a LIB file.
You need to use the
A.LIB
as Linker Input in project B. Just producing LIB file wont make other projects automatically link to it.