Extending a C++ class at runtime????

Started by
32 comments, last by GameDev.net 18 years, 9 months ago
Hello I'm trying to find a way to link at run time to a class implemnetation. It's like this: I have a class, lets say AAA with function foo implented and compiled in an exxutable module. The class AAA is to be extended by another class BBB in a dynamic link library module and be able to use/inherit the AAA implentation of memebr function foo. It could be done in C as there by passing pointers to the function foo at run time, but this if could be done in C++ somehow will break the rule of many C++ features and it will become useless to use C++. Is there a way to do this like exporting virtual tables so that the BBB class can link to the functions in AAA? BTW I have looked at a similar thing in the game Sin source code which uses plain C for the core engine and the game code which is C++ is passed pointer to the C function at runtime. But what I want is a way to keep everything C++ and link at runtime. Thanks.
Advertisement
Quote:Original post by quaker
I have a class, lets say AAA with function foo implented and compiled in an exxutable module. The class AAA is to be extended by another class BBB in a dynamic link library module and be able to use/inherit the AAA implentation of memebr function foo.



You'll need to place AAA into a shared library (DLL) and include the necessary import/export declaration in the class declaration as such:


#ifdef CREATE_AAA_DLL#define AAA_EXPORT __declspec(dllexport)#else#define AAA_EXPORT __declspec(dllimport)#endifclass AAA_EXPORT AAA {};



This will instruct the compiler to export the attributes, methods, and vtable of AAA (with full C++ name mangling) in the DLL.
And then?

This works if you want to link statically with a library, or at runtime but you need to create an object first to access the methods.

My question is much more complex and I've been thinking about it for too long trying to find a reliable and practical solution that does not affect the main C++ purpose.
And then you write a creator function. That's the entry point the host application will use to instantiate your class even without knowing its name.

__declspec(dllexport) class BBB : public AAA{public:    virtual void foo() { ... }};__declspec(dllexport) AAA* Create(){    return new BBB;}
Oh, and then in your host application you do something like this:

AAA* CreateSubclassOfAAA(const std::string &name){    HMODULE hmodule = LoadModule((name + ".dll").c_str());    AAA*(*creator)() = GetProcAddress(hmodule, "Create");    return creator();}
Thanks. but this is not what I'm asking about.

//inside the excutable module EXE

class AAA {

void foo();

}

void AAA::foo() {
......
}

//inside a dll module

class BBB : public AAA {

void myfoo();
}

BBB::myfoo()
{
foo(); // call AAA's foo implemntation first
.....
}

Then the EXE file use your suggestion to make instances of BBB ok I know that, but how to get AAA::foo() implemntation at runtime whether it's declared virtual or not?
quaker: Not sure I understand the last post.

Fruny's method returns a pointer to a derived type -- a pointer to a base class (AAA) should be easy to cast into the derived class (BBB), should it not?

Therefore, calling class AAA's Create() method will, depending on the DLL linked, generate a correct instance flawlessly.

I think that's how it all should end up working, even though I don't understand the OP.




DISCLAIMER: Nothing in this post is guaranteed to be true or even well-informed.

EDIT:
Quote:but how to get AAA::foo() implemntation at runtime whether it's declared virtual or not?
Hmm...if AAA::foo() is declared virtual, it may be overwritten by the generated instance of BBB.

This is how I'd try implementation:
AAA* base = new AAA;//decide which DLL to load, determining implementation of class::foo()...base = Create();  //generate a new instance of that class//base is now, in Fruny's example, a "new BBB"base->foo(); //calls BBB::foo()

But, as with all technical answers I attempt to mess up, don't quote me on that. Unless somebody smart comes along and says "Yes, that's right, and it's a correct way to use interfaces to write extensible code. You're so awesome, Boku San." Then you can touch quote me.

EDIT AGAIN AFTER ACTUALLY READING THE LAST POST: Also, if you're looking to extend a class generically (google "interfaces"...or something like that), you won't want to add any methods to extending classes (BBB) -- instead, rename BBB's myfoo() to simply foo() and allow it to call AAA::foo(), if it's necessary.
(...I gotta stop editing)
Things change.
Look at the Sin source code thoroughly and you will get my question.

But this source is not pure C++ since the engine part which originally a Quake 2 engine written in plain C. But the game code/logic/entities is C++ calling core engine functionalities through pure C calls.

But this is not purely OO approach.
Ah and doing it as you suggest:

BBB::myfoo() {
base->foo(); // this will invoke the intended function on the wrong object
// it's not called for (this) object of BBB
.......

}
You need to use implicit linking if you want to call non-inline functions from a separate dll like that. Sneftel's example uses explicit linking where you use GetProcAddress() to get the function by name. With implicit linking you have a .lib file which you statically link which contains stub functions which forward to the dll at runtime. In this case your base class would have to be defined with exported functions and your derived class would link statically to the import library created when you build the base class module. If you export functions from your main executable the linker will create an import library for the exe so you don't necessarily need to break your base class out into a separate dll for this to work. When you use implicit linking the runtime handles loading the dlls for you automatically so there's no need to call LoadLibrary() or GetProcAddress(). Search MSDN for 'linking dll' and you should turn up the info you need.

Game Programming Blog: www.mattnewport.com/blog

This topic is closed to new replies.

Advertisement