I would like to understand the DLL mechanism and what the compiler does when I loads the DLL at run-time (i.e. I will not use the generated .lib).
Consider the following C++ code:
DLL interface header file
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class MYDLL_API Base
{
public:
  Base();
  virtual ~Base();
  virtual int get_number() const;
  virtual const char* what() const = 0;
private:
  int i_;
};
class MYDLL_API Child : public Base
{
public:
  Child();
  virtual ~Child();
  virtual int get_number() const override;
  virtual const char* what() const override;
private:
  int j_;
};
extern "C" {
  MYDLL_API Base* __cdecl initializeObject();
}
DLL implementation source file
#include "MyDLL.hh"
Base::Base()
  : i_(42)
{}
Base::~Base()
{}
int Base::get_number() const
{
  return i_;
}
Child::Child()
  : Base()
  , j_(24)
{}
Child::~Child()
{}
int Child::get_number() const
{
  return j_;
}
const char* Child::what() const
{
  return "Hello!";
}
Base* initializeObject()
{
  return new Child();
}
The goal of this DLL is to have a common interface defined by the Base class, but it allows specifics implementations compiled in different DLLs that are loaded at runtime (here the Child class is exposed for the purpose of the example).
At this stage, if I naively include the DLL's header:
#include "MyDLL.hh"
int main()
{
  Base* b = new Child();
  std::cout << b->get_number() << std::endl;
  std::cout << b->what() << std::endl;
  delete b;
  getchar();
  return 0;
}
The linker complains LNK2019 and LNK2001 errors: it can not resolves symbols. So, it behaves as expected (I did not use the .lib).
Consider now, the following code that I use to load the DLL at runtime:
#include "MyDLL.hh"
typedef Base* (*initFuncType)();
int main()
{
  HINSTANCE handle = LoadLibrary(L"MyDLL.dll");
  initFuncType init = nullptr;
  init = (initFuncType)(GetProcAddress(handle, "initializeObject"));
  if (init)
  {
    Base* b = init(); //< Use init() !
    std::cout << b->get_number() << std::endl;
    std::cout << b->what() << std::endl;
    delete b;
  }
  getchar();
  FreeLibrary(handle);
  return 0;
}
This time it works, the linkage is done.
- 1st question: What happened? What changed for the compiler and the linker? The use of the function pointer on initializeObject() solves the problem.
The other issue I do not understand well is when I remove virtual and override of get_number():
int get_number() const;
I have a LNK2019 error because of the unresolved Base::get_number(void) const symbol in the _main function. I understand that the virtual keyword will resolve the member function dynamically (at run-time). In our case, the DLL is not loaded yet, the get_number symbol is not available.
- 2nd question: Does this means that methods must always be - virtualusing DLL run-time linking?
- 3rd question: How can I have the C++ function exportation with the Windows API? So that I could remove the - extern "C" { ... }stuff.
Thanks for your reading! I hope I will read interesting answers! :)
 
    