• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 374
  • Last Modified:

Derived Classes and DLLs

Here's my problem.  So far, I have been programming some DLLs with __declspec(import and export)  I have just classes  (and callback functions, which are not my problem so n/m)  I am making a rendering class, with a base class, and modules for differnet renderers, DirectX, OpenGL, SoftWare, etc.  I have the basic Render class has the basic functions with no definitions, and the derived classes are the actual rendering devices that have the functions (from the base class)  are defined.  My problem is this, I want to have the base class compiled with the __declspec() but the derived classes to be loaded dynamically so that all rendering devices are not all loaded at once, and this will make room for people to compile their own rendering modules themselves.  I have read how to load simple functions from a DLL with LoadLibrary, GetProcAddress (or whatever)  and all those functions, but I want to know how to load an entire class, without having to typedef each seperate function then prototypeing from the typedef then loading from the DLL to the prototype, this just seems like too much work and I hope there's a quicker and more simplisitic way, without having to have multiple headers for the classes for build and runtime.  Can anyone help?  (Or understand what I mean)
  • 5
  • 2
  • 2
1 Solution
This can be done by using virtual functions (it would be nearly impossible without them).  I think I have a "prewwritten" answer on this.  I'll see if I can find it.
************ Base.h*******
// Note no export directive.  Not of any value for you
// since you are linking at run-time.
class Paths {
 public :
         Paths() ;
        // note all functions are virtual, because linking
        // is to be done through the VTBL  No need for
        // GetProcAddress().
         virtual ~Paths() = 0;;
         virtual int DoSometingWith (int x, int y)  = 0;
         vitual char* SomethingElse (int v, char *w) = 0 ;

// Type defintition for the "factory" function.
typedef Path * (*MakePtrTyp)();

#inlude "Base.h"

// Derived concrete class.  Functions can be added here that
// are not virtual, so long as they are not to be used by the EXE.
// Any functions the EXE uses must be virtual.
class DerivedPaths : public Paths
         DerivedPaths() ;
         virtual ~Paths()  {};
         virtual int DoSometingWith (int x, int y)  { return x+y; };
         vitual char* SomethingElse (int v, char *w)  { return w+v; } ;

// The factory function.  Uses extern "C" so that it is easier for
// the EXE to get using GetProcAddress();
extern "C" Paths *MakePaths()
    return new DerivedPaths;

   HINSTANCE PathLib = Loadlibrary("some path");
   MakePtrTyp MakeProc = (MakePtrTyp) GetProcAddress(PathLib,"MakePaths");

   Paths *PathsPtr = (*makeProc)(); // Make a paths object.

   delete PathsPtr;

A couple more words of explanation.  

The only time you need to use GetProcAddress() with this scheme is to find the factory function in the DLL that creates the objects.  All the other functions are handled through virtual functions calls.  That is obviously much more convenient than lots of GetProcAddress() calls!

The DLL allocates objects using new and the EXE eventually deletes it with delete.  For this to work the two must share a common heap, this means you must use the DLL version of the run-time library.  (a good idea in any case.)  Another alternative is for the DLL to have a function that does the delete, but I would do the other.

The EXE can load different DLLs that define different derived classes.  So if the derived class has different versions or changes with time, the EXE does not need to be recompiled.

This approach is in many ways the C++ version of COM.
That is an example, but not an explanation.  What you need to do is to make all the public functions of the class virtual.  And you do not need to export them from the DLL (but you can, it just doesn't matter).  This is so that the virtual table will be used to find the right procedure to call at run time.  This is is important because you (realistically) cannot use the return value from GetProcAddress() to call a non-static member function.  So we get around this by using virtual functions.

Now you will need to use GetProcAddress() still, but only for one thing, which is nice because it is inconvenient to use!  when you need to create a object you will use GetProcAddress() to call a factory function in the DLL.  To be specific, each DLL will have an exported function with a specific name (or ordinal) and this function will return a pointer to a dynamically allocated object of whatever class this DLL is supposed to create.  Now the object returned by the DLL is of a class derived from the class the EXE "knows" about.  The EXE doesn't "know" about the derived class.  But that is fine.  The factory function creates the class and the virtual functions manipulat the class, so the EXE only needs to "know" about the base class.

Let me know if you have any questions.
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

XycsoscyXAuthor Commented:
I accepted the answer because it works now, with one workaround.  When I compiled at first, I got an error  (when I compiled the DLL for the derived class)  Since I have to use the base class as : public RenderSystem (which is what I am using)  But I get an error when I compile saying the Initializer and DeInitializer from the base class are not defined.  My temporary workaround was to define the Init and DeInit within the Derived class modules seperately, but I want to have the functions for the Init and DeInit of the base class with the exe itself, not the seperated modules.  How can I fix this?
I'm not really following you.  Are you tallking about constructors and destructors, or other functions?


Did you get this error when compiling the EXE or the DLL?  You might get this when compiling the DLL....   If so, I think you're going to have to place these functions in the base class's include file, so they are placed in each module.  

another option, might be to export the the functions from the class in the EXE and then link the DLL with the EXE's .lib file.   That sort of technique is actually posible.  (havig a DLL use exports from the EXE that loads it.)  but I've never done it and there may bother steps invloved and adding the fact that these are member functions could compilcate it.
XycsoscyXAuthor Commented:
Okay, thanks, I thik what I wil to is make my base renderer a dll  (well, actually base render, input, sound, etc)  and export the classes to it, so I have it and the dll, then link my derived classes to the lib from the base dll, and link the exe to this base dll also.....thank for all your help.
I used the code Nietod code and I find it great!
But I have a trouble: my "MakePaths" function is exactally the same, I can use pointers returned by this function to call virtual function and everithing is all right.
But my program crashes vhen I call the
"delete" on this pointers!

Any suggestion?
Are you using the DLL version of the run-time library (RTL)?  You need to.  The static RTL will not work for this.

From another question:


The problem is that if the EXE and DLL use the staticly linked version of the run-time library (RTL), they each have their own seperate copies of the RTL.  These copies each have thier own seperate heaps for allocating memory with the new operator.   The problem is that each one does not "know" about the other.  So for example, if the DLL allocates memory, the memory comes from the heap in the DLL's copy of the RTL.  If a pointer to that memory is passed back to the EXE (it may be passed in a subtle way, like inside a class) and if that EXE later makes changes that require that the memory specified by the pointer be deleted, then the EXE will try to delete the memory, but will not be able to find the memory inside its heap.  This is is because the memory did not come from the heap.  Hence the problem.

The solution is to have the EXE and all the C++ DLLS that it uses link with the DLL version of the RTL.  Then the EXE and all the DLLS will share a single copy of the run-time library and will therefore share a single heap.

To set this in VC:

"Project" menu
"Settings..." menu item
in the dialog box that appears  "C/C++" tab
"Code generation" Category
in "Use run-time library:" select one of the DLL options.

(There are two DLLoptions there, one for a debug version, one for a release version.  Make sure you choose the setting that is right for the version you are creating)

Note that these settings need to be changed for EVERY version (debug. release etc) of the EXE and and DLLs that is shares memory with.
thanks nietod for your answer.
You had already told that I need to use the Dll version of the RTL or call a member function for deleting the object, but I didn't read carefully your previous answer.

I chosed to implement a Release function in the dll, because I dont want to have any trouble with future .exe that may need to use the Static RTL.

Once again, this is COM!
thanks a lot
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

  • 5
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now