I have a big project where an executable A.exe
is generated (with a cmake toolchain) to dynamically load B.dll
at run-time . But without compile-time linking with B.dll
, I got "unresolved external symbol" when building the executable.
The project organized like this:
superproject | |--- build/ |----CMakeLists.txt |--- src/ | |---a : a1.cpp, CMakeLists.txt |---b : bh, b.cpp, export.def, CMakeLists.txt
file src/b/bh :
class Machine
{
int u;
static Machine* sing;
public:
Machine();
static Machine* GetInstance();
int answer();
};
file src/b/b.cpp :
#include "b.h"
Machine* Machine::sing;
Machine::Machine() : u(1) {}
Machine* Machine::GetInstance()
{
if (!sing)
sing = new Machine();
return sing;
}
int Machine::answer(){ return u + 33; }
Machine* GetMach()
{
return Machine::GetInstance();
}
file src/a/a1.cpp :
#include <windows.h>
#include <iostream>
#include "b.h"
using namespace std;
typedef Machine* (*func_t)();
int main(int argc, char* argv[])
{
cout << "hello\n";
HMODULE lib = LoadLibrary("b.dll");
if (lib)
{
void* rawfunc = GetProcAddress(lib, "GetMach");
if (rawfunc)
{
func_t func = (func_t)(rawfunc);
Machine* m = func();
cout << "The exported number is " << m->answer();
}
else
{
cout << "Failed to get the symbol";
}
}
else
{
cout << "Failed to load library";
}
getchar();
return 0;
}
file src/b/export.def :
EXPORTS
GetMach
file src/b/CMakeLists.txt :
file(GLOB_RECURSE SRC_FILES *.cpp)
file(GLOB_RECURSE DEF_FILES *.def)
add_library(b MODULE ${SRC_FILES} ${DEF_FILES})
file src/a/CMakeLists.txt :
file(GLOB_RECURSE SRC_FILES *)
include_directories(../b)
add_executable(A ${SRC_FILES})
Visual Studio complains of:
error LNK2019: unresolved external symbol "public: int __cdecl Machine::answer(void)" (?answer@Machine@@QEAAHXZ) referenced in function main C:\....\superproj\build\a\a1.obj A
Why have I got this error and how to eliminate it?
From the linker's point of view, non-virtual method ( Machine::answer
) is the same as global function (say, GetMach()
).
That is, for being able to use this method, A
should either:
target_link_libraries
) with a library defining the method or GetProcAddress()
). If both of these approaches seems inconvinent, you may declare the method as virtual :
virtual int answer();
All virtual methods are resolved at runtime . A linker doesn't bother about using of virtual methods.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.