[C++] How to GetProcAddress() like a boss
When programming on Windows, you usually use the functions from another DLL through an  import .lib that links the functions used in your program with the functions exported by a DLL.
Manual DLL loading
However, there are a few situations where you cannot use this scheme:
- You may simply not have the required import 
.lib - You may want to delay load the library to improve startup time
 - You may not know the names of the functions at compile time
 - You may not know the name of the DLL at compile time
 - You may want to load a DLL that is not in the search path.
 
In these situations, you need to do the job of the .lib manually:
- Call 
LoadLibrary()to load the DLL in your process - Call 
GetProcAddress()with the name of each function you want to use - When finished, call 
FreeLibrary()to unload the DLL 
The Good Old Way
Here is how you would do in C:
typedef int(WINAPI *ShellAboutProc)(HWND, LPCSTR, LPCSTR, HICON);
int main() {
  HMODULE hModule = LoadLibrary(TEXT("Shell32.dll"));
  ShellAboutProc shellAbout =
      (ShellAboutProc)GetProcAddress(hModule, "ShellAboutA");
  shellAbout(NULL, "hello", "world", NULL);
  FreeLibrary(hModule);
}
Which could be OK if you just have to import one function but would quickly become a nightmare when more functions are imported.
In this code snippet, there are three pain points:
- You need to have the 
typedefexactly right - You need to make sure that you don’t call 
FreeLibrary()too soon - There is a lot of repetition
 
The Modern C++ Way
It turns out that you could use C++ to fix each:
- You can use 
decltype()to extract the type from the declaration present in the header file. - You can use RAII to load and unload the library
 - You can use implicit cast operator to reduce the repetition.
 
First, let’s see the code in action:
class ShellApi {
  DllHelper _dll{"Shell32.dll"};
public:
  decltype(ShellAboutA) *shellAbout = _dll["ShellAboutA"];
};
int main() {
  ShellApi shellApi;
  shellApi.shellAbout(NULL, "hello", "world", NULL);
}
Not only this is more readable, but it’s also more scalable: you can add more functions in the ShellApi class and it will stay simple.
How it works
Now let’s see what’s inside the box:
class ProcPtr {
public:
  explicit ProcPtr(FARPROC ptr) : _ptr(ptr) {}
  template <typename T, typename = std::enable_if_t<std::is_function_v<T>>>
  operator T *() const {
    return reinterpret_cast<T *>(_ptr);
  }
private:
  FARPROC _ptr;
};
class DllHelper {
public:
  explicit DllHelper(LPCTSTR filename) : _module(LoadLibrary(filename)) {}
  ~DllHelper() { FreeLibrary(_module); }
  ProcPtr operator[](LPCSTR proc_name) const {
    return ProcPtr(GetProcAddress(_module, proc_name));
  }
  static HMODULE _parent_module;
private:
  HMODULE _module;
};
First, the ProcPtr class wraps the return value of GetProcAddress() so that it can be implicitly casted to any function type (There is an SFINAE to prevent a cast to anything else).
Then the DllHelper class implements the RAII and exposes a convenient operator[] that calls GetProcAddress().
That’s all!
The full code of this article is available on GitHub.