c++templatesgetprocaddress

How to dynamically define member functions in C++


I have this object what is just a wrapper around an external dll, in Windows. On creation of the object, the constructor queries the registry for the key, then queries this key's value for the folder with the dll, then loads the dll, gets the ProcAddress of this dll's initializator, and initialises it.

Then, I want to offer to other clients all the functionality of this dll, so my class-wrapper offers member functions what will check if we have GetProcAddress'it, if not then we do it, get the pointer to this function, and call it.

I don't want to do all the GetProcAddress'es at constructor time because there are hundreds of functions and is very likely that a given client will need only a small bunch of them, so GetProcAddress'ing everything is a waste.

But now, I need to define these functions, and it feels like a gigantic copy&paste thing. All the member functions are doing exactly the same, something like

ResultType Wrapper::pertainingMemberFunction(...)
{
    if (this->pointerToPertainingDLLFunction == nullptr) {
        this->pointerToPertainingDLLFunction =
            reinterpret_cast<pertainingType>(GetProcAddress(HMODULEDLL, "pertainingName"));
    }
    return this->pointerToPertainingDLLFunction (...);
}

And this really feels like a very sub-optimal solution. I'm feeling there must be some way to templatize all this code to be generated at compile time correctly. Or perhaps the initial approach was not the best to begin with, I'm not sure.


Solution

  • It's simple enough to factor out the logic into a function template:

    template <class Function, class... Args>
    decltype(auto) getProcAddressAndCall(
        Function *&function,
        char const *name,
        Args &&... args
    ) {
    
        if(!function)
            function = reinterpret_cast<Function *>(GetProcAddress(HMODULEDLL, name));
    
        return function(std::forward<Args>(args)...);
    }
    

    ... which you can then call with:

    ResultType Wrapper::pertainingMemberFunction(...)
    {
        return getProcAddressAndCall(pointerToPertainingDLLFunction, "pertainingName", ...);
    }