Skip to main content
GameDev.net gamedev.net
🔒 Locked

dll & virtual & dynamic_cast

Started by aboeing Dec 29, 2004 at 2:47 AM 7 replies 2.4k views
Original Post
aboeing
aboeing
Hi, I'm just wondering if anyone can give me advice on using virtual functions, and dynamic_cast with a DLL? Basically, the situation is like this: -A dll contains a class 'Example : public aExample', which is created via a call like so: extern "C" __declspec(dllexport) void *CreateComponent() {return new Example;} -The class contains a virtual function 'Register' -The Register function is called by the main program, after loading the DLL and calling the CreateComponent function. Now the problem is in VC6, this all seems to work, until I try and do: aExample *e=dynamic_cast(the_example_class); and dynamic_cast fails. If I try static_cast it works. I googled, and found that GCC has a bug similar to this, and assumed VC6 also had this bug. When I try and compile with VC7 it will not even call the virtual 'Register' function, and so nothing at all happens. Any possible ideas as to what is going on? Thanks.
Drew_Benton
Drew_Benton
With .dlls, you cannot return new memory for use in a program because .dlls have their own memory. Take a look at the Plugin class that's on my web page, I'm not trying to promote it - but there are some useful links and code on accompishing what I think you are doing.

I know that I always called a reinterpret cast to change void* to a pointer of a different type, so you can also try that.
NLDEV
NLDEV
Quote:
Original post by aboeing
Now the problem is in VC6, this all seems to work, until I try and do:
aExample *e=dynamic_cast(the_example_class);
and dynamic_cast fails.
If I try static_cast it works. I googled, and found that GCC has a bug similar to this, and assumed VC6 also had this bug.

When I try and compile with VC7 it will not even call the virtual 'Register' function, and so nothing at all happens.

Any possible ideas as to what is going on?

Thanks.


What type is the_example_class?

Quote:
With .dlls, you cannot return new memory for use in a program because .dlls have their own memory.

You can pass memory allocated from another module (say, a DLL) to another module (say, your application). You're just going to want to free the memory in the module it was allocated. This is my experience, at least.
aboeing
aboeing
Quote:
Original post by Drew_Benton
there are some useful links and code on accompishing what I think you are doing.

Yep. Thats exactly what I'm doing. Thanks a boat load!

edit:
Actually, its a little different from what I'm doing.
I'm a little confused:
// Create new memory for a OpenGLWindow	__declspec(dllexport) void Get_OGLWindow( IWindow** ppMem )	{		// We cannot simply return new memory!		*ppMem = new OpenGLWindow;	}

is this any different from:
myFactoryObject* Create() {return new name;}
aboeing
aboeing
Quote:
Original post by MikeMJH
What type is the_example_class?

Sorry, I should have mentioned, its an 'Example' class -- or at least it should be.

Quote:
You can pass memory allocated from another module (say, a DLL) to another module (say, your application). You're just going to want to free the memory in the module it was allocated. This is my experience, at least.

Yes, this seemed to work for me in the past too.
aboeing
aboeing
Sorry guys, I just did a reboot, clean, and now everything works fine (well with VC7, so I'm assuming dynamic_cast with VC6 is a bug). :) Thank you for your help, next time I will try the reboot scenario before posting.

drew: One thing I added to my plugin-style system that you might find usefull aswell is to have a 'group' id, so that you can set the group id to 'OpenGL' or 'DirectX' and then every class you create will automatically be the correct corresponding class.
Kibble
Kibble
Quote:
Original post by aboeing
Quote:
Original post by Drew_Benton
there are some useful links and code on accompishing what I think you are doing.

Yep. Thats exactly what I'm doing. Thanks a boat load!

edit:
Actually, its a little different from what I'm doing.
I'm a little confused:
// Create new memory for a OpenGLWindow	__declspec(dllexport) void Get_OGLWindow( IWindow** ppMem )	{		// We cannot simply return new memory!		*ppMem = new OpenGLWindow;	}

is this any different from:
myFactoryObject* Create() {return new name;}

The return method will not work across all compilers, the pointer to a pointer method will. If you want a DLL to work with your program no matter what compiled it, use the pointer to a pointer method. There is nothing wrong with returning memory though, and you are right, there is not any difference other than how it gets called by some compilers.
Polymorphic OOP
Polymorphic OOP
Quote:
Original post by Drew_Benton
With .dlls, you cannot return new memory for use in a program because .dlls have their own memory.

As was said, yes, you can use objects dynamically allocated in DLLs, you just have to make sure that when you deallocate them, you do so from the DLL. This is usually done simply by having a virtual member function which deletes itself (since the virtual function is defined for the object inside the DLL, the deletion is fine).

dynamic_cast and other RTTI is usually not going to work across executable boundaries, such as from an exe using objects in a DLL, since the methods used for RTTI utilitize information about the object known at build-time or load-time of the executable I.E. a unique value automatically generated per type, or even the memory location of a vtable, etc.

Take those example implementations with two executables -- each executable includes the same complete class definitions, however, this means that each executable also generates its own RTTI information (with the former solutuion, those generated values may be different between executables and, taking the latter solution, the vtable locations will be different). You may think "why not have the executable communicate the appropriate information to the DLL when the DLL is loaded and adjust RTTI operations appropriately," but then you face the problem that multiple executables can load the same DLL at one time, using the same functions inside the DLL, meaning that the type information would be potentially different for each executable which loads it. So you're stuck in terms of what stuff can be done automatically for you.

Because of this, using dynamic_cast across DLL boundaries is no simple task. Even though the associated objects in each executable may be functionally the same, using dynamic_cast on a pointer to an object in another executable will not give you proper results.

Instead, you have to resort to your own form of RTTI to determine the type, or probably preferably, just don't rely on any RTTI at all, as it's usually a sign of poor design to begin with.
Drew_Benton
Drew_Benton
Quote:
Original post by aboeing
Sorry guys, I just did a reboot, clean, and now everything works fine (well with VC7, so I'm assuming dynamic_cast with VC6 is a bug). :) Thank you for your help, next time I will try the reboot scenario before posting.

drew: One thing I added to my plugin-style system that you might find usefull aswell is to have a 'group' id, so that you can set the group id to 'OpenGL' or 'DirectX' and then every class you create will automatically be the correct corresponding class.


There are a lot of bugs in VC6 :(. As for the plugin stuff - still working on it. Thanks to Kibble for all his feedback :). Much appreciated.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.