   Class Creation Problem
  Hi, I've got a problem that I was hoping someone could help me with.  I've done tons of searching and haven't come up with anything satisfactory, just a few dead ends.My issue is with the game engine I'm writing.  All my game entity objects for my scene manager are derived from the Entity class.  There are a few predefined derived classes from Entity, but I'd like to extend it such that the client application of the engine's DLL can create it's own derived classes.  This is all fine and everything, until it meets my memory manager class.  To delete these entities in the memory manager part of the engine's DLL, they must have been created (with new) within the DLL also.So herein lies my problem.  I need to be able to have a method for the DLL itself (preferably within the scene manager) to instantiate arbitrary classes derived from the base Entity.At first, I thought it would be a simple matter of adding a templated member function to the scene manager such astemplate< class T > Entity *SceneManager::CreateSpecialEntity( ){return (Entity *)(new T( ));}This, of course, failed miserably, since the DLL is unable to create a copy of the code for the application's classes.My second attempt was to pass a pointer to a static function within the derived class that would create an instance of itself and return a pointer, but that again failed.So, being out of ideas, I'm asking for help here.  Anyone?  Please?   
Quote:Original post by Ray1234This is all fine and everything, until it meets my memory manager class.  To delete these entities in the memory manager part of the engine's DLL, they must have been created (with new) within the DLL also.What's so special about your memory management that enforces this condition?Maybe you just need to link to DLL core-run-time? Or is it somewhat more complicated?And as for your original problem: try overloading new operator for the classes that need to take memory from "someplace", then, let this overloaded operator kindly ask the DLL for the memory (that would be independent from any template instantiation issues).   ;  Have you consider not making subclasses to specialize your objects and using compostion instead ? You could then create Entity specialization at runtime and leave your memory manager instanciate all Entity, which you would specialize afterwards.There is a nice article about that in GP Gems 6.   ;  I did a quick search on Google and found this article and it's even on GameDev:http://www.gamedev.net/reference/articles/article2097.aspHope that gives you what you are looking for.   ;  Even simpler.header:class Entity{  //...  void* operator new(size_t size); // do not implement here!!!!11};DLL:void* Entity::operator new(size_t size){  return ::operator new(size); // or from some mem-manager.};APP:class MyEntity : public Entity{  // nothing speceial here  // ...};And when new MyEntity() is invoked the code flow will jump to DLL part, since only there will be implementation of the overloaded operator new.Or am I on the wrong track?~def   ;Quote:Original post by defferWhat's so special about your memory management that enforces this condition?Maybe you just need to link to DLL core-run-time? Or is it somewhat more complicated?And as for your original problem: try overloading new operator for the classes that need to take memory from "someplace", then, let this overloaded operator kindly ask the DLL for the memory (that would be independent from any template instantiation issues).Nothing special, really.  Objects within the engine are reference counted and the memory manager is responsible for deleting them after all their references are released.  You simply have to delete objects within the same scope as they were created (dll-created objects have to be delete within the dll, application-created objects must be deleted within the application.)I'll look into the new operator to see if it's possible with what I'm attempting to do.Quote:Original post by jantaHave you consider not making subclasses to specialize your objects and using compostion instead ? You could then create Entity specialization at runtime and leave your memory manager instanciate all Entity, which you would specialize afterwards.There is a nice article about that in GP Gems 6.Thanks, I'll check this out when I have time tonight.Quote:Original post by CyberCowboyhttp://www.gamedev.net/reference/articles/article2097.aspNeat article, but doesn't really apply to my situation.  That's the gist of what I'm trying to do, but it relies on all the objects being defined within the same DLL/exe as the factory.Just to give a better example of what I'm trying to do:I have my Entity class, as mentioned above.  As a child of this, defined within the engine DLL, I have a PagedTerrain class which handles dynamically streaming in/out terrain data for the viewer.What I'd like to do is be able to, in my terrain editor, create a derived class of PagedTerrain called EditablePagedTerrain that would work identically as far as the engine and scene manager are concerned, but would provide the application with functionality to modify the terrain and those results would be apparent in its output to the renderer.The issue is that since EditablePagedTerrain is derived from PagedTerrain, Entity and finally MMObject (the reference counted object base class), the memory manager will eventually try to delete it.  If I just create an instance of it within the application and toss it to the scene manager to work with, once the application is closed, it will cause a nasty error and probably leak any memory created after it, along with any DirectX resources it was using and any that were unable to be released because it had yet to release its own.   ;Quote:Original post by Ray1234You simply have to delete objects within the same scope as they were created (dll-created objects have to be delete within the dll, application-created objects must be deleted within the application.)Sorry, I still can't see the reasons for that. Could you elaborate on this some more?Quote:Original post by Ray1234The issue is that since EditablePagedTerrain is derived from PagedTerrain, Entity and finally MMObject (the reference counted object base class), the memory manager will eventually try to delete it.  If I just create an instance of it within the application and toss it to the scene manager to work with, once the application is closed, it will cause a nasty error and probably leak any memory created after it[...]Hmm...This doesn't sound like a job for overloaded new.This sounds like a job for virtual destructor.   ;Quote:Original post by defferHmm...This doesn't sound like a job for overloaded new.This sounds like a job for virtual destructor.Well, the overloaded operator new didn't work, same issue as without it.The destructor is virtual already.Quote:Original post by defferSorry, I still can't see the reasons for that. Could you elaborate on this some more?It's an issue of the DLL having a different heap than the application EXE.  Things created in one heap cannot be deleted from another.  Since the DLL deletes all of these sorts of objects in my engine, they must all, therefore, be created within the DLL also.   ;Quote:Original post by Ray1234Well, the overloaded operator new didn't work, same issue as without it.The destructor is virtual already.(I'm assuming you overloaded operator delete as well.)And it didn't work, you're saying...APP<->  DLLnew MyEntity();operator new->    implemented hereget memory!!constructor(s) [...]delete p;virtual destructordestructorsoperator delete  ->    implemeted herefree memory!!Is this the scenario? If not, please tell me where I'm wrong.Quote:Original post by Ray1234It's an issue of the DLL having a different heap than the application EXE.  Things created in one heap cannot be deleted from another.  Since the DLL deletes all of these sorts of objects in my engine, they must all, therefore, be created within the DLL also.That's understandable. However - you can always switch to single heap, linking to Run-Time Library from MSVCR71.DLL (/MD switch in MSVC). If you have reasons not to, those are the actual reasons I don't see.   ;Quote:Original post by Ray1234So herein lies my problem.  I need to be able to have a method for the DLL itself (preferably within the scene manager) to instantiate arbitrary classes derived from the base Entity.I can't see how you would be able to do this. To be able to create an object using operator new, you have to know the class at compile time. If you don't, you won't be able to execute the constructor of the object. In a plugin-driven system, it means that you can't create instances of classes that are only known by the plugin without using some kind of proxy (ie you need to create the instance in the plugin). There is no other way to do it. Of course, it also means that you have to delete the instance from within the plugin too - this is not what you want, but hey, this is what you have to do [smile]. However, there is a solution to your problem : your plugin can register a factory whose goal will be to call placement new on already allocated memory in order to call the entity class constructor. class MyEntityFactory : public EntityFactory{public:  virtual size_t getEntitySize(int type) const   {    switch (type) {    case MY_ENTITY_1: return sizeof(MyEntity1);    case MY_ENTITY_2: return sizeof(MyEntity2);    case MY_ENTITY_3: return sizeof(MyEntity3);    }    return 0;  }    virtual Entity *create(void *p, int type)  {    switch (type) {    case MY_ENTITY_1: return new(p) MyEntity1;    case MY_ENTITY_2: return new(p) MyEntity2;    case MY_ENTITY_3: return new(p) MyEntity3;    }    return NULL;  }  virtual Entity *destroy(Entity *e, int type)  {    switch (type) {    case MY_ENTITY_1: e->MyEntity1::~MyEntity1; break;    case MY_ENTITY_2: e->MyEntity2::~MyEntity2; break;    case MY_ENTITY_3: e->MyEntity3::~MyEntity3; break;    }    return NULL;  }};class MemoryManager{  // the plugin factory should be some kind of global in the   // plugin; at least, it should exist as long as the plugin  // is loaded, and while it exists it should be registered   // in the main factory (the memory manager, in my case)  std::vector<EntityFactory*> mFactories;public:  Entity *createEntity(int type)  {    // find the factory that will be used to create the entity    for (size_t i=0; i<mFactories.size(); i++) { size_t s = mFactories->getEntitySize(type); if (s) {    // allocate the memory    char *p = new char;<br>    <span class="cpp-comment">// call the constructor</span><br>    Entity *e = mFactories<span style="font-weight:bold;">-&gt;create(<span class="cpp-keyword">reinterpret_cast</span>&lt;<span class="cpp-keyword">void</span>*&gt;(p), type);<br>    <span class="cpp-keyword">if</span> (e) {<br> <span class="cpp-keyword">return</span> e; <br>    }<br>    <span class="cpp-keyword">delete</span> [] p;<br> }<br>    }<br>    <span class="cpp-keyword">return</span> NULL;<br>  }<br>  <br>  <span class="cpp-keyword">void</span> deleteEntity(Entity *e)<br>  {<br>    <span class="cpp-comment">// find the factory that has been used to allocate e</span><br>    <span class="cpp-keyword">for</span> (size_t i=<span class="cpp-number">0</span>; i&lt;mFactories.size(); i++) {<br> size_t s = mFactories<span style="font-weight:bold;">-&gt;getEntitySize(e-&gt;type());<br> <span class="cpp-keyword">if</span> (s) {<br>    <span class="cpp-comment">// call the destructor</span><br>    Entity *e = mFactories<span style="font-weight:bold;">-&gt;destroy(e, e-&gt;type());<br> }<br>    }<br>    <span class="cpp-comment">// delete the allocated memory</span><br>    <span class="cpp-keyword">delete</span> [] <span class="cpp-keyword">reinterpret_cast</span>&lt;<span class="cpp-keyword">char</span> *&gt;(e);<br>  }<br>};<br><br><br></pre></div><!–ENDSCRIPT–><br><br>Voilà. HTH,