Archived

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

good stuff: abstract, interface, COM, dynamic link,etc...

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

here we go again first of all some conditions: - C++ - OOP - portable IUnknown
class IUnknown
{
public:
    Inknown(){mRefCount = 1};
    virtual ~IUknown(){};

    void AddRef(){++mRefCOunt};
    void Release(){if(!--mRefCoutn) delete this;};

private:
    uint  mRefCOunt;
};

extern "C"
{
    IUnknown*     Create();
}
ILogger
class ILogger: public IUnknown
{
public:
    ILogger();
    virtual ~ILogger();
    virtual void Output(const string&) = 0;
private:
};

ILogger::ILogger(): IUnknown()
{}

ILogger::~ILogger()
{}
TextLogger DLL
class TextLogger: public ILogger
{
public:
    TextLogger();
    virtual ~TextLogger();
    virtual void  Output(const string&);
private:
};

TextLogger::TextLogger(): ILogger()
{
    // do

}

TextLogger::~TextLogger()
{
    // do

}

void TextLogger::Output(const string& lString)
{
    // write lString to file

}

IUnknown* create()
{
    return(new TextLogger)
}
IShell
class IShell: public IUnknown
{
public:
    IShell();
    virtual ~IShell();
    virtual IUnknown* CreateFromFile(const string&) = 0;
private:
};

IShell::IShell(): IUnknown()
{}

IShell::~IShell()
{}
ShellWin32
class ShellWin32: public IShell
{
public:
    ShellWin32();
    virtual ~ShellWin32();
    virtual IUnknown* CreateFromFile(const string&);
private:
};

ShellWin32::ShellWin32(): IShell
{}

ShellWin32::~ShellWin32()
{}

IUnknown* ShellWin32::CreateFromFile(const string& lFilePath)
{
     IUnknown*    lPtr     = 0;
     IUnknown*  (*lFncPtr) = 0;
     typedef IUnknown* (*TYPE)();  // for create


     HINSTANCE	lDLLLib	= LoadLibrary(lFilePath.c_str());

     if(lDLLLib != 0)
     {
        lFncPtr = (TYPE)::GetProcAddress(lDLLLib,"Create");
	if(lFncPtr !=0)
	{
		lPtr	= lFncPtr();
	}
     }
     FreeLibrary(lDLLLib);
     return(lPtr);
}
main
ShellWin32    shell;
ILogger*      log = 0;
log = dynamic_cast<ILogger*>(shell.CreateFromFile("logger.dll"));
if(log)
{
    log->Output("bastard");
    log->Release();
}
so... hit me!!! the code does compile and link, but when i run it, i get an exception... questions: 1) is this correct approch? 2) umm... more to come

Share this post


Link to post
Share on other sites
You called FreeLibrary before your call to ILogger::Output. Don't do that. Free it after you've finished with everything in the DLL. Remember, GetProcAddress returns a function pointer inside the DLL's codespace . FreeLibrary deletes that codespace, leaving you with a wild pointer.

EDIT: A better method would be to store your lDLLLib handle as a member variable in the ShellWin32 class. Then you can just call FreeLibrary in your destructor.

[edited by - ShoelessManiac on June 3, 2003 10:06:14 AM]

Share this post


Link to post
Share on other sites
i fixed the FreeLibrary "bug/feature", but that still didnt sovle the issue...



however, i found out that the problem was in casting...

when i changed

log = dynamic_cast<ILogger*>(shell.CreateFromFile("logger.dll"));


to

log = (ILogger*)(shell.CreateFromFile("logger.dll"));

everything worked fine...

can somebody enlighten me why?

[edited by - original vesoljc on June 3, 2003 11:08:04 AM]

Share this post


Link to post
Share on other sites
Just for clarification, what kind of exception were you getting and who was throwing it? Was it from you create function? or from the dynamic_cast?

Share this post


Link to post
Share on other sites
quote:
Original post by original vesoljc
when i changed

log = dynamic_cast<ILogger*>(shell.CreateFromFile("logger.dll"));


to

log = (ILogger*)(shell.CreateFromFile("logger.dll"));

everything worked fine...

can somebody enlighten me why?

Are you checking the pointer being returned by the dynamic_cast? It needs to be a pointer to an ILogger or an accessible base of ILogger for the cast to work, else you will get NULL. That might be a start point. In the second piece of code, you''re using a c-style cast, which might translate as a reinterpret_cast. You''ve not really provided enough details to know exactly what''s going on.

Share this post


Link to post
Share on other sites
@Sabreman:

i checked pointer returned by dyn_cast and it was "valid" (as i could see from the debugger ).
log was declared as ILogger*, and dll exports a create func which returns a pointer to newly created TextLogger: public ILogger.


IUnknown* create(){ return(new TextLogger)}


please correct me if /me wrong:

i dynamicly create a new object TextLogger(base ILogger) and downcast(?) its ptr to a IUnknown*. right?

and when i wish to assign this ptr to my global log ptr, i do an upcast(?) to ILogger*.


log = (TYPE_TO_BE)variable
what kind of a cast is this again?


extern "C"{ IUnknown* Create();}

i''ve read that this was good?
name mangling something?


@fizban
exception came from casting, which i dunno


anyway, it kinda works ok now, will have to check it if all desc are being called :D

one more question:
if a base class has assignment operator, it''s sub(?) class also has assign operator, what''s the proper way to call base operator?



SUB_CLASS& SUB_CLASS::operator=(const SUB_CLASS& lRight)
{
if(&lRight != this)
{
// do base class assigment

BASE_CLASS::operator =(lRight);
// do SUB_CLASS assigment

}
return(*this);

Share this post


Link to post
Share on other sites