Jump to content
  • Advertisement
Sign in to follow this  
Kris_A

Dynamically loading class methods

This topic is 4078 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

Hiya, I've finally been getting around to learning the more OOPy side of C++, rather than just the C-style procedural stuff. I'm trying to find a way to do something similar to this:
class OBJECT {
	private:
		int thisvar;
		int thatvar;
	public:
		void ThisMethod();
		void LoadMethods(char*);
};
void OBJECT::LoadMethods(char * dll) {
	// Load DLL with LoadLibrary, and replace
	// 'ThisMethod' with method loaded from the DLL
}
int main() {
	OBJECT myobj;

	myobject.ThisMethod(); // Calls standard version of the method	

	myobj.LoadMethods("somedll.dll");

	myobject.ThisMethod(); // Now calls somedll.dll version of method

	// ... 
}
Assumably, inside the DLL it'd look something like this:
__declspec(dllexport) void OBJECT::ThisMethod() {
	// Do something specific to this DLL
}

I'm pretty sure I've seen this being done somewhere before, but I'm not sure what it's called, so I haven't been able to find much useful information about it. Hooray for forums! Any help (even the name of this paradigm) would be greatly appreciated. Thanks!

Share this post


Link to post
Share on other sites
Advertisement
The first bit of confusion that needs clearing up is the fact that this has nothing to do with "object oriented" design or programming whatsoever. All you're talking about is dynamically loading some code, and all you're doing differently (you imply) is using classes. Classes don't make code object-oriented in and other themselves, however.

The next issue is: why are you doing this? It's not required to use DLLs in general, and its ugly. It's likely that your specific situation may warrant a much cleaner solution.

In any case, the basic premise will be that each concrete method in OBJECT will need to naively forward to a function pointer, and the function pointer will have to initially point to a (presumably private) method in the class:

class Object
{
public:
Object() : myFunctionImpl(&ConcreteMyFunctionImpl) { }

int MyFunction(int foo,int bar) { return myFunctionImpl(this,foo,bar); }


private:
int (*MyFunctionImplPtr)(Object*,int,int);

MyFunctionImplPtr myFunctionImpl;

static int ConcreteMyFunctionImpl(Object *self,int foo,int bar);
};


Note that MyFunction delegates to a non-member function pointer, and is initially set up to point to a static function. I'll get to the reasoning shortly.

Then, in the Object::LoadMethod() function (which I omitted from the above sample for brevity), you load the DLL and call GetProcAddress() to obtain function pointers to all the appropriate functions in the DLL. Then you update each function pointer field in the class to point to the function pointers you loaded from the DLL.

The reason I used a non-member function pointer and manully set up the "this" ("self") parameter was because the name you pass to GetProcAddress needs to match the name in the exports table -- that name will decorated if the method was dllexport'd (see here, and C++ decorated names are very ugly, and implementation-defined. Although on Windows, if you don't mind depending on an extra Windows DLL, you can use UndecorateSymbolName(). In any case, making the actual implementation function non-members makes the entire process less painful. You could get an implementation working using members... but it would nastier.

So, that's the general process (at least the tip of the iceberg) in a nutshell. If you can give me an idea of the specific requirements you have, and why, I can probably provide a better option.

Share this post


Link to post
Share on other sites
Ahhh, that makes sense, thanks.

The reason I'm doing this is, I'm making a little system of components linked together (similar to Widget Workshop). The components only perform minor operations (add, multiply, etc), but you can link them together to do more interesting stuff. Sort of like a VPL.

Im storing all objects in DLLs so they can be user-made, but still be easy to program on my behalf. I realise this has security implications - are there any better ways of doing this, that don't require me to invent a brand new language? Is Windows' security attribute system enough to stop malicious code from being executed?

thanks again

Share this post


Link to post
Share on other sites
It seems with such small objects you'll end up with massive DLL bloat. I do something similar, but for shader languages so I can simply store textual data and connect that together (in a tool similar to the now-defunct ShaderWorks) and other artist-centric shader construction tools; but I digress).

C++ is really not ideal for this, at least as the implementation language for the widgets. What I would do instead is design an API that would be used to program the widgets (perhaps you've done this already?) Then expose that API to a scripting language, such a Lua, AngelCode, or Python. I've personally used Lua the most so I can provide direct input regarding techniques for doing that.

Then your widgets become data, instead of code, as far as C++ in concerned.
A widget could be a binary file containing some image and other properties (assuming you're going for something very similar to those screenshots) and a block of text written in the scripting language that you load and compile and execute as a script.

This will likely be a lot cleaner and more powerful than the DLL route, while at the same time allowing you (after a bit more initial effort) more easily build new widgets. A few hours with C# and WinForms, even if you've never used either, can yield you a decent, user-friendly widget builder, too.

[Edited by - jpetrie on April 20, 2007 1:36:07 PM]

Share this post


Link to post
Share on other sites
ahh, Lua, I never thought of that! Perhaps I'll try binding that to my API, when it's finished. thanks once again :D

edit: been messing around with it, I was suprised how easy it was to compile and bind with C++ :o

[Edited by - Kris_A on April 21, 2007 10:22:27 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!