Jump to content
  • Advertisement
  • entries
    437
  • comments
    1000
  • views
    337042

Musings on Plugins

Sign in to follow this  
evolutional

123 views

I've solved a horrible bug in GMGX thanks to Fluid Studios (again). I was building collision masks and randomly writing to bits of memory I didn't own - it was only when more started happening did we get random crashes.

The SDL renderer seems to be working very well, thanks to Joel Longanecker's SDL tutorials. I like dealing with SDL actually, I've never used it before except as a launching pad for OpenGL apps. I'm writing to the screen buffer and doing all the stuff I used to have to think about in 'the old days' of game coding. It's nice to see I'm not too rusty with it all! I'm concerned about the whole 'clear screen/redraw' approach I'm taking right now (thanks, OpenGL!) and the affect it might have on framerate later on.

And to respond to yesterday's comments:-

Quote:
Original post by rick_appleton
Theoretically, this setup would allow me to compile for each and every platform with the same makefile (assuming it builds the to-build list from directory contents), but only changing a single, or possibly two defines.


I took a leaf out of your book and removed all the platform/API specific cpp files from my build process and instead included them with the help of a few defines. I was already defining my platform, so it wasn't a major change. It seems to be working nicely - thanks for the tip - it saves me building many different makefiles now :)

The following is a response to Jack's idea mentioned in my last entry...

An interesting approach for plugins... In theory, it's possible provided you supply a global ISystem class for each system to register to.

For example:


class ISystem;

class IPlugin
{
public:
explicit IPlugin( ISystem *a_system )
{
// hash name
setHashedName( GetName() );
}
virtual ~IPlugin() { }

virtual const char *GetName() const = 0;

unsigned int GetSystemHandle() const;
void SetSystemHandle(unsigned int a_systemHandle);

unsigned int GetHashedName() const;

protected:
ISystem *m_system;
unsigned int m_hashedName;
unsigned int m_systemHandle;

void setHashedName( unsigned int a_hash ) { //generate a hash of 'name' and store; }
};

class ISystem
{
public:
virtual ~ISystem() { }

virtual IPlugin *LoadPlugin( const char *a_name ) = 0;
virtual void ReleasePlugin( IPlugin *a_plugin ) = 0;

virtual IPlugin *GetPlugin( const char *a_name ) = 0;
};

class System : public ISystem
{
public:
virtual ~System() { }

protected:

void registerPlugin( IPlugin *a_plugin )
{
// store in map for later retreival by name
}

// map of plugins, key is a hash of plugin name
std::map< int, IPlugin *> m_plugins;
};

class Win32System : public System
{
public:

IPlugin *LoadPlugin( const char *a_name )
{
// Load module (a_name + .dll), look for 'CreatePlugin' function in DLL - store it in *p
IPlugin *plg = (*p)( this );
plg->SetSystemHandle( // hmodule handle );
registerPlugin( plg );
return plg;
};

void ReleasePlugin( IPlugin *a_plugin )
{
// get system handle from IPlugin, release it
}

};




Or something along those lines. To use the system, you'd have to implement the plugin interface in your DLL:-


class HelloPlugin : public IPlugin
{
public:
explicit HelloPlugin( ISystem *a_system );
virtual ~HelloPlugin() { }

const char *GetName() const { return "hello"; }

};

// export
__declspec(__dllexport) IPlugin *CreatePlugin( ISystem *a_system ) { return new HelloPlugin( a_system ); }


Then to consume the plugin you'd do something like:


int main()
{

#if defined( __WIN__ )
Win32System sys;
#elif defined( __LINUX__ )
LinuxSystem sys;
#else
#error "Unsupported platform"
#end


IPlugin *plg = sys.LoadPlugin( "hello" );

// If you know what type of plugin to expect (eg: graphics, sound, etc)
// you can probably cast
HelloPlugin *hello = 0;
if ( ::stricmp( "hello", plg.GetName() ) == 0 )
{
hello = reinterpret_cast< HelloPlugin* >(plg);
// do stuff with hello...
}

};


If you don't like the idea of casting on an assumption of name, you could probably have a set of standard "OnLoaded", "OnExecute", "OnReleased" type virtual event handlers to allow a certain amount of genericity (is that a word?). An extension of this would be to define a set of plugin 'types' in an enum - each of these types would have an associated interface:

Eg:


enum
{
PLGT_UNKNOWN = 0,
PLGT_UTILITY,
PLGT_GRAPHICS,
PLGT_SOUND,
PLGT_SCRIPTING,
// etc
};

// Then the baseclasses:
class IPlugin;
class IUtilityPlugin : public IPlugin; // Contains a generic utility interface
class IGraphicsPlugin : public IPlugin; // Contains a generic graphics interface
class ISoundPlugin : public IPlugin; // A generic sound interface
class IScriptingPlugin : public IPlugin; // A generic script binding interface


The plugin would export its own class/typeid which would then let you (more) safely assume the baseclass for a plugin and cast to that.

Eg:


IPlugin *plg = sys.LoadPLugin( "glRenderer" );

if (plg.GetType() != PLGT_GRAPHICS)
// Error, we were expecting this to be a graphics plugin

IGraphicsPlugin *gfx = reinterpret_cast(plg);

// then later on:-

gfx->ClearScreen();
gfx->BeginRender();
// etc


Of course, this would require the engine and the plugins to always be in sync, but would allow for them to know 'something' about each other for inter-plugin/system communication.
Sign in to follow this  


2 Comments


Recommended Comments

Quote:
thanks to Fluid Studios (again)

I'm not sure what I'd do without that tool [grin]

Okay, I suppose I have the VS memory leak tools - but somehow they never seem to work as well.

Quote:
The following is a response to Jack's idea mentioned in my last entry

What you described pretty much covers everything I intended - except yours makes sense!

I'm gonna have to try something like that one day..

Jack

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • 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!