Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

SilentReaper

Classes in a DLL / plugins

This topic is 5826 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello all. I am working on a game project where I''d like to exclusively use C++ and classes. One of the requirements of this project is that it must be easy to upgrade/patch the game components and add things to the game (such as new weapons, new characters, or new AI behaviors). To this end, each major component of the game will have a sub-directory where I''d like to read in and load *.DLL. I have read some of the prior posts on how to use C++ in DLL''s and how to access those classes in the hosting process, however these posts have all pretty much been what I consider "early bound". The classes are known and defined at compile time. That won''t necessarily be the case with my game. If a new DLL is dropped in a directory, its code should run. I was planning on making a basic parent class with at least 3 pure virtual functions: - init: set up any variables necessary, possibly pass in a "this" pointer from one of my master classes so that the class can access other game objects - process: called in the appropriate game logic section (a weapon class would be processed during the weapons stage of the game loop) - shutdown: release all allocated memory objects and handles. I don''t believe this type of scenario was answered in any prior posts (if so, someone please link me there), and I can''t seem to find any GOOD resource on Google. Is this possible? Could someone help me out with a short snippet? Doesn''t even have to be to my above specs as long as I learn the requirements for creating the DLL and how to load in the DLL into my game process.

Share this post


Link to post
Share on other sites
Advertisement
What you are after is called a "pluggable factory", searching for that on Google will return you loads of articles. Indeed one of them is right here at GameDev.

[edited by - MonkeyChuff on August 14, 2002 11:08:17 AM]

Share this post


Link to post
Share on other sites
Sweet! I will look for that. You are not, by any chance, referring to COM are you? I would like to steer clear of that since I have heard it is very slow. I know COM has things called class factories, and that is the only reason I ask.

[edited by - SilentReaper on August 14, 2002 11:13:15 AM]

Share this post


Link to post
Share on other sites
No, not at all, factory''s are a common design pattern, it just so happens that COM uses the factory pattern quite extensively.
I haven''t found COM to be slow, most of DirectX uses COM, so if you are going down that route then it''s going to be in there somewhere.

Share this post


Link to post
Share on other sites
Its a peice of cake. Crystal space does a good job of explaining how its done: http://crystal.sourceforge.net/docs/online/manual/cs_139.php

If you want a more specific example:

iTest.h:
class iTest
{
public:
virtual int Init(void* stuff)=0;
virtual int Process()=0;
virtual int Shutdown()=0;
};


Test.h:
class Test: public iTest
{
public:
int Init(void* stuff);
int Process();
int Shutdown();
};



Test.cpp:

int Test::Init(void* stuff)
{
//do something
return 0;
}
int Test:: Process()
{
//do somthing
return 0;
}
int Test::Shutdown()
{
//do somthing
return 0;
}

//this is called the class factory
__declspec(dllexport) Test* ExportPlugin()
{
return new Test;
}




main.cpp:

#include "itest.h"
#include <windows.h> //yuck!
HINSTANCE handle;
typedef void* (*FuncPtr)();


int main()
{
FuncPtr funcpointer;
handle=LoadLibrary("test.dll");
funcpointer=GetProcAddress(handle,"ExportPlugin");
iTest* tester=funcpointer();
tester->Init(junk);
tester->Process();
tester->Shutdown();
FreeLibrary(handle);
return 0;
}


test.h and test.cpp are compiled into test.dll
main.cpp is compiled into the main program, both use itest.h

basically what you have to do, is search through all the dlls in your games 'plugin' folder and call GetProcAddress to get the pointer to the ExportPlugin function, if you get a null returned then that dll isnt one of your plugins, if a !null pointer is returned then call the function the pointer points to and store the returned pointer as a pointer to base plugin class...

'ExportPlugin' isnt a special function name, you can name it whatever you want...

a couple things to watch out for if you use MSVC...

In order to export a function with a specific name(MSVC likes to give functions semirandom names) you have to give it a specific option or use a .def file. not hard to do. You can check the actuall name that is exported by generating a .map file(its an option) and looking in there.

make sure the function calling convention in the dll class factory and the function pointer match otherwise you get nasty errors

ummm i think thats it, hope it helps!

[edited by - warpexplorer on August 14, 2002 5:33:04 PM]

Share this post


Link to post
Share on other sites
Thank you to you both for your excellent resources! warpexplorer: I assume that if I derive from Test that iTest will still work? I assume that it would and the reason for it would be the vtable would have the proper location for my member functions?

Thanks again!

Share this post


Link to post
Share on other sites
I tried something very similar to that and got errors, which I think come from the fact that new uses some memory allocation function (malloc?), which uses global pointers (buckets, if anyone understands). The dll had it''s own copies of these variables, which meant there were two separate memory allocation functions each trying to allocate the same memory.

(I''m guessing this because when mallocing large (1mb - 256bytes) blocks, one from the dll and one from the main, the pointers were different by a number not divisible by 1meg. If you know malloc, this is wrong. Also, nonsensical pointer errors abounded)


Constructors are able to be exported themselves from the DLL, without the need for an encapsulating function like the one below.

If you use MSVC 6 or more, create a new project of type "Win32 dynamic link library", and chose "A dll that exports some symbols". It gives examples of how to create dlls "well" (the microsoft way). It shows how to export variables, functions and constructors.

Also, dlls shouldn''t call library functions unless you know what you''re doing. A simple call to printf() will not print anything when inside a dll, you have to import the printf function (or an encapsulating function) from the main program. I assume this doesn''t work for the same reason that I assume malloc doesn''t.

(These are just my findings, correct me if I''m wrong)

Share this post


Link to post
Share on other sites
Krylloan,

well, im not sure about new using malloc.
but my above example works perfectly on my machine as long as the call convention is the same.

The examples microsoft give are for ''statically'' linked dlls (very oxymoron), they MUST be (and are) loaded when the program starts and are unloaded when it exits. Which doesnt work for what SilentReaper wants.

all the library functions that I''ve tried work in my dlls (SDL, OpenGL, stdio, ect.)
printf works great, all i have to do is #include <stdio.h>

I use MSVC 6 so I dont think its a compiler problem, are you sure you are using the same calling convention?

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!