MSVC unresolved external symbol linking executables
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 come开发者_如何学Cs 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?
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 is foo.cpp
. When compiled, there should be a foo.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 the foo.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.
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.
精彩评论