locked
Run time Dynamic linking of C++ RRS feed

  • Question

  • Is there any way to use C++ classes which are defined in a DLL and this DLL is linked dynamically at run time i.e. using LoadLibrary? I have declared a C function in DLL which creates the instance of the my class and returns the pointer to it. This C function and C++ class both are exported from DLL. In the EXE, i have included the header file of my class and call LoadLibrary and GetProcAddress to load the DLL and get the address of the exported C Function. When i call this function i get the instance of my class but when i try calling any function on this instance then i get linking error of unresolved symbols.
    Sunday, October 3, 2010 3:36 PM

Answers

  • On 03/10/2010 17:36, sramya1234 wrote:

    Is there any way to use C++ classes which are defined in a DLL and this DLL is linked dynamically at run time i.e. using LoadLibrary?

    To follow this path, I'd suggest to export a factory function with a pure-C interface, and use a C++ abstract class (i.e. an interface, like COM does) instead of an ordinary C++ class.

    e.g. in your DLL header you can define:

       struct ISomething
      {
           virtual int DoSomething() = 0;
           virtual void DoSomethingElse(...some params...) = 0;
           virtual void Cleanup() = 0;
      };
    

    and then export a factory function like this:

       // DLL factory function for ISomething
      extern "C" __declspec(dllexport)
        ISomething * __stdcall CreateSomething(void);
    

     The client code calls CreateSomething() using LoadLibrary/GetProcAddress and then uses the interface methods, like this:

       ISomething * pSomething = CreateSomething();
       pSomething->DoSomething(...);
      ...
      pSomething->Cleanup();
    

     HTH,
    Giovanni

    • Proposed as answer by Carl Daniel Monday, October 4, 2010 3:43 AM
    • Marked as answer by sramya1234 Monday, October 4, 2010 4:51 AM
    Sunday, October 3, 2010 5:32 PM
  • Is it true that this technique works because in case of virtual function the resolution of functions is deferred till run time so the linker does not need a function definition?
    Only a function declaration is needed to call a virtual function, so as long as the function that you supply at runtime matches the declaration that was used at compile time, everything will work. 

    Even though i have put extern "C" i still need to use the mangled name like

    _FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "_GetMyClass@0")

    That's not a C++ mangled name, but rather is a __stdcall name for a "C" function. 


    -cd Mark the best replies as answers!
    • Marked as answer by sramya1234 Monday, October 4, 2010 5:02 AM
    Monday, October 4, 2010 3:46 AM

All replies

  • On 03/10/2010 17:36, sramya1234 wrote:

    Is there any way to use C++ classes which are defined in a DLL and this DLL is linked dynamically at run time i.e. using LoadLibrary?

    To follow this path, I'd suggest to export a factory function with a pure-C interface, and use a C++ abstract class (i.e. an interface, like COM does) instead of an ordinary C++ class.

    e.g. in your DLL header you can define:

       struct ISomething
      {
           virtual int DoSomething() = 0;
           virtual void DoSomethingElse(...some params...) = 0;
           virtual void Cleanup() = 0;
      };
    

    and then export a factory function like this:

       // DLL factory function for ISomething
      extern "C" __declspec(dllexport)
        ISomething * __stdcall CreateSomething(void);
    

     The client code calls CreateSomething() using LoadLibrary/GetProcAddress and then uses the interface methods, like this:

       ISomething * pSomething = CreateSomething();
       pSomething->DoSomething(...);
      ...
      pSomething->Cleanup();
    

     HTH,
    Giovanni

    • Proposed as answer by Carl Daniel Monday, October 4, 2010 3:43 AM
    • Marked as answer by sramya1234 Monday, October 4, 2010 4:51 AM
    Sunday, October 3, 2010 5:32 PM
  • Thank you. It worked.

    I have one thing to ask...

    Is it true that this technique works because in case of virtual function the resolution of functions is deferred till run time so the linker does not need a function definition?

    One question:

    Even though i have put extern "C" i still need to use the mangled name like

    _FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "_GetMyClass@0")

     

    I will just illustrate here about the program so others also can get benefited.

    I have created a DLL which has a class. I need to dynamically load this DLL in my EXE at run time i.e. I am trying to explicit dynamic linking for loading C++ class from this DLL.

    My Class Header File...

    // MyClass.h

    #include "MyInterface.h"

    class MyClasss : public MyInterface

    {

        public:

    void show ();

    }

    You can see that this class is publicly inherited from another class "MyInterface". Here is the definition of "MyInterface"

    // MyInterface.h

    class MyInterface

    {

    public:

    virtual void show () = 0;

    };

    extern "C" 

    __declspec(dllexport) MyInterface* __stdcall GetMyClass();

     

    Here is source file for MyClass

    //MyClass.cpp

    #include "MathClass.h"

    #include <iostream>

    using namespace std;

    void MyClass::show ()

    {

       std::cout << "Invoked" << std::endl;

    }

     

    extern "C" __declspec(dllexport) MyInterface* __stdcall GetMyClass()

    {

    return new GetMyClass();

    }

    Now build this as DLL and you will have MyClass.DLL in the debug folder.

     

    Here is the exe that access it.

    #include "Interface.h" 

    typedef MyInterface* (*FunctionFunc)();

    int main ()

    {

     FunctionFunc _FunctionFunc;;

     HINSTANCE hInstLibrary = LoadLibrary (TEXT("MathDLL.dll")); // Load DLL

    _FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "_GetMyClass@0"); // Get the pointer to C function

     MathInterface* m = (MathInterface*)_FunctionFunc (); // Get the Instance

     m->show(); //call Function

     return 0;

    }

     


    Saurabh Ramya
    Monday, October 4, 2010 2:40 AM
  • Is it true that this technique works because in case of virtual function the resolution of functions is deferred till run time so the linker does not need a function definition?
    Only a function declaration is needed to call a virtual function, so as long as the function that you supply at runtime matches the declaration that was used at compile time, everything will work. 

    Even though i have put extern "C" i still need to use the mangled name like

    _FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "_GetMyClass@0")

    That's not a C++ mangled name, but rather is a __stdcall name for a "C" function. 


    -cd Mark the best replies as answers!
    • Marked as answer by sramya1234 Monday, October 4, 2010 5:02 AM
    Monday, October 4, 2010 3:46 AM
  • On 04/10/2010 04:40, sramya1234 wrote:

    Thank you. It worked.

    You're welcome.

    I have one thing to ask...

    [...]


    _FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "_GetMyClass@0")

    Carl already answered your questions.

    Note that according to rules of name-decoration convention shown here:

    http://msdn.microsoft.com/en-us/library/zxk0tw93(VS.80).aspx

    - an underscore is prefixed to the name (GetMyClass --> _GetMyClass)
    - the name is followed by @ sign (_GetMyClass@)
    - there follows the number of bytes (0 in this case, because GetMyClass has no parameters (void)) -> _GetMyClass0

    If you don't want decorations for __stdcall functions, you can use .DEF files. Using .DEF files, you can just export "GetMyClass" from the DLL.
     One more note following:

    extern "C"

    __declspec(dllexport) MyInterface* __stdcall GetMyClass();

    Here is the exe that access it.

    > [...]


    #include "Interface.h"

    typedef MyInterface* (*FunctionFunc)();

    You should adjust the above typedef. In fact, you should specify the correct calling convention here:

      typedef MyInterface* (__stdcall *FunctionFunc)();
    

     Giovanni

    Monday, October 4, 2010 9:57 AM