HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Calling a function from a dynamically loaded DLL

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
dlldynamicallyfunctionloadedcallingfrom

Problem

I need to implement some functionality of the otherwise monolithic application via DLL that is loaded at runtime. (Think about a customized DLL -- different for each customer.)

The Visual C++ from VS 2013 is used.

The application gets the full name name of the DLL. The function to be called has a fixed name (convert in my case) and fixed number and type of the arguments (a reference to a constant vector of strings -- see the cref_vs below). This means the function is implemented in C++.

I have modified the example from the MSDN doc, and it seems to work. However, I must be sure I did not overlooked something important. Here is the code (simplified) to load the DLL and call the function:

typedef const std::vector & cref_vs;
typedef int(*CONVERTPROC)(cref_vs vs);


Notice that unlike in the official example that mixes calling a C code in DLL from a C++ function, I do not use __cdecl. I guess that this way I can reliably pass a C++ object (like a vector of strings). Is it correct?

int call_convert_from_dll(const std::string & dllname, 
                          const std::vector & vs)
{
    HINSTANCE hinstLib;
    CONVERTPROC convert;
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

    // Get a handle to the DLL module.
    hinstLib = LoadLibrary(dllname.c_str());

    // If the handle is valid, try to get the function address.
    if (hinstLib != nullptr) {
        convert = (CONVERTPROC)GetProcAddress(hinstLib, "convert");

        // If the function address is valid, call the function.
        if (convert != nullptr) {
            (convert)(vs);
        }

        // Free the DLL module.
        fFreeResult = FreeLibrary(hinstLib);
    }

    if (!fRunTimeLinkSuccess)
        return 1;

    return 0;
}


Now, because I want the unmangled name of the function inside the DLL, I need to use extern "C", and it must be exported via __declspec(dllexport). However, I do not want to use __cdecl calling convention:

```
#include
#include

Solution

Short answer: No, but I won't hold it against you. ;)

I'd suggest reading up on using C++ with DLLs in a compatible fashion, and would suggest this excellent article as a good place to start. This article also touches on exporting STL types, which your code is doing.

So, the question is, how portable/robust do you need/expect your approach to be? If you need developers from anywhere to be able to plug into your system, stick to a C interface if possible (avoiding STL types -- pass a char** across the boundary, and convert that on the C++ side to an STL vector). Otherwise, upgrade to a virtual class based system -- and make sure that you don't directly use STL, but instead use virtual class wrappers for those types as well. Note that this carries on -- e.g., if you want to use an iterator class used by the STL type you're wrapping, you'll need another abstract (iterator) class that your abstract (iterable) class references, so it can get a little ugly.

Minor code notes...

  • fFreeResult is assigned, but never used.



  • fRunTimeLinkSuccess is not set (after initialization).



  • The "convert" string might better be contained in a macro (or a small set of macros), so that your plugin clients can declare a convert function, and you can refer to that function name without the possibility of typo.



  • Your example plugin refers to argc and argv that don't exist.

Context

StackExchange Code Review Q#48224, answer score: 3

Revisions (0)

No revisions yet.