• Advertisement

Archived

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

abstract classes on dll's

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

so, i create an abstract class, derive from it, create a concrete class or two of them and implement them in the dll. i''m using two functions like create_interface and free_interface, which take an adress of a pointer "on" which the object is created. next step is to load the dll (dynamicly) and get the address of these two functions (sort of a factory), which are then being used to create and free objects. the prototypes for these functions are defined in the abstract class header. now, if using lets say ten or twetny diffrent abstract objects, this means that i need ten or twenty diffrent create/free functions. this seems kinda ummm... "stupid". is there a more functional approach?

Share this post


Link to post
Share on other sites
Advertisement
forget the freeing (see COM objecs.. )


  
interface IUnknown {
void addRef() { ++refCount; }
void release() { if(!--refCount) delete this; }
virtual ~IUnknown() {}
IUnknown() : refCount(1) {}
private:
unsigned int refCount;
};


my base object, from wich all others are derived from.. inspired by COM..

but yet, for every object a creation function (or some creation function with parameters for several creation functions.. but in the end.. you want to be able to create each one in some or another way..)

btw, i never use the pointer actually, but i''ve made this small wrapper class

  
template<typename Type> class Interface {
typedef Type SavePointer; //unsave, but helps with the intellisence of vc7

/* class SavePointer : public Type {
private:
void addRef();
void release();
};*/

public:
Interface(Type* ptr) : pointer(ptr) { pointer->addRef(); }
Interface(const Interface<Type>& other) {
pointer = other.pointer, pointer->addRef();
}
Interface<Type>& operator=(const Interface<Type>& other) {
if(this != &other) {
pointer->release();
pointer = other.pointer;
pointer->addRef();
}
return *this;
}
~Interface() { pointer->release(); }
SavePointer* operator-> () { return static_cast<SavePointer*>(pointer); }
protected:
Interface() : pointer(new IUnknown) { }
void setPointer(Type* ptr) {
if(ptr) {
pointer->release();
pointer = ptr;
}
}
IUnknown* pointer;
};


then, for each and every object.. it looks like this:

public header:

  
#include "IUnknown.h"

interface IObj : IUnknown {
virtual void sayHello() = 0;
};

IObj* createObj();

class Obj : public Interface<IObj> {
public:
Obj() {
setPointer(createObj());
}
};

wich lets me use my Obj as a POD.. works more or less like a pointer..

say this:

  
void func(Obj obj) {
obj->sayHello();
}

int main() {
Obj obj;
func(obj);
}

and memory management works automagically


implementation of obj:

  
#include "IObj.h"

struct CObj : IObj {
void sayHello();
CObj();
private:
Some data;
};

void CObj::sayHello() {
out<<"Hello"<<end;
}

CObj::CObj() {
data = SomeData();
}

IObj* createObj() {
return new CObj;
}


thats about it.. oh, i forgot.. #define interface struct
hehe:D

"take a look around" - limp bizkit
www.google.com

Share this post


Link to post
Share on other sites
Assuming the abstract types aren't related one to another, about the only thing I can see you do is write a factory class template, then create one instance for each abstract base type. You'll still have 10 to 20 functions in the end, C++ won't let you get away without them, but at least you won't have to write them N times.

To manage object lifetime, boost::shared_ptr works nicely - it lets you register your release function to be called automatically.

Edit: good job davepermen.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]


[edited by - Fruny on February 2, 2003 6:36:27 PM]

Share this post


Link to post
Share on other sites
this is why my game i am working on dosent use a lot of classes and whatnot.
not that it is a badthing.

automagicaly - nice...

dynamic sigs are fresh!

Share this post


Link to post
Share on other sites
thanks, fruny..

i''ve used a very similar template class to wrap all dx9 objects.. very cute to work with:D

uhm.. AfTeRmAtH (uh. terrible to write:D).. well.. in the end, usage of this gets damn easy, so what? and it was fun to learn a bit more about com..

automagically, yeah.. the trendword of davepermen.. i use c++ to handle all stuff for me (livetime of "new" data, etc..).. i don''t do anything manually. i give c++ the rules of my objects, and it handles it automagically..
thats the power of c++.. saves me from being stupid:D

"take a look around" - limp bizkit
www.google.com

Share this post


Link to post
Share on other sites
My game, as I said, is what I use it in.

Hold it now, my engine that powers the game is another different thang. I use all that C++ crap; classes, superclasses, polymorphism, new, templates, and all the jaaaazzzzzz.

I just wanted to even out my l33t programming skills by stopping all that OOP crap and do a bit of old-school’in… just a bit.

If that didn’t make sense to you… “I am not a crook”

dynamic sigs are fresh!

Share this post


Link to post
Share on other sites
quote:
Original post by Ready4Dis
trendword of davepermen? I''ve been using it for well over 5 years now .


thats why i didn''t said trendword.. but for me, its new(er), and i use it as a trendword in my vocabulary:D

"take a look around" - limp bizkit
www.google.com

Share this post


Link to post
Share on other sites
okidoki...
one thing still bothers me...
i created IUnknown class and a template class Interface,
i then define my interface struct LoggerADT with pure virtuals, like:

    
interface LoggerADT: public IUnknown
{
public:
void info (char*,...) = 0;
void error(char*,...) = 0;
// etc..

};


do i still need to declare "create function" prototype here?
like:
extern "C"
{
LoggerADT* CreateLogger();
}

then, i create new dll project, which has a concrete class and a def file which exports CreateLogger.

dll header:

  
class TextLogger: public Interface<LoggerADT>
{
public:
void info(char*,...);
// etc..

}

since we allready have a creation function prototype, we just have to implement it.
but, i'm getting conversion errors when trying something like this:

  
LoggerADT* CreateLogger()
{
return(new TextLogger);
}

i tried reinterpret_cast, but this gets an error:
"cannot instantiate abstract class due to following members..."
what am i missing?

one more thing: i still have to "manualy" (getprocaddress) find the address of our creation function in the dll? so i still "need" function typedef:
typedef void (*MYTYPE)() [/source]

[edited by - original vesoljc on February 18, 2003 4:37:17 AM]

Share this post


Link to post
Share on other sites
i fixed few things:
first the create func:

    
LoggerADT* createlogger()
{
LoggerADT temp = null;
temp = new textlogger;
return(reinterpret_cast<LoggerADt*>temp)
}

in my textlogger constructor a new file is created (opened and closed) and in my destructor the file is just appended.
so if i do:

LoggerADT* gpLog;
// load dll, get address

gpLog = lpCreateFunc;
delete(gpLog);

i get the expected results... (file is created and text appended from destructor)
but i call any of the member functions via -> operator (defined in template class Interface) i get an access violation...
why again?

one more thing:

  

gpLog = lpFunc(); // break point

gpLog->Debug("blabla"); // break point

delete gPlog;

at the second break point i check gplog object, it is !null, but sub-object IUnknown seems strange, coz refcount is not set to 1 as expected, but to extremlly large number... (44769853488090572 -i'm using unsigned 64bit int for counter)
this ofcourse is not correct but i cant find the reason for it
[edited by - original vesoljc on February 18, 2003 5:49:31 PM]

[edited by - original vesoljc on February 18, 2003 5:56:42 PM]

Share this post


Link to post
Share on other sites
TextLogger has to be derived from LoggerADT..

your interface

  
interface ILog {
virtual void log(char*) = 0;
};

__declspec(dllexport) ILog* create();

in your dll:


  implementation CLog : ILog {
void log(char*);
};

void CLog::log(char*) { ... }

__declspec(dllexport) ILog* create() { return new CLog; }


in the exe, using it:

  
ILog* log = create();
log->log("text");
log->release();

or, if you want to wrap

  
class Log : public Interface<ILog> {
Log() { setPointer(create()); }
};

Log log;
log->log("text");



"take a look around" - limp bizkit
www.google.com

Share this post


Link to post
Share on other sites

  • Advertisement