VincentP
Programmer
- Apr 1, 2001
- 116
I am trying to do somthing which is not really intented to do in C++, I think... My ultimate goal is to have my VC++ 6 program create instances of objects which are not compiled into the EXE. (Some sort of fake Run-Time class declaration).
In other words: I want to create a card playing program, and I want the program to look for all different versions of AI it can find and use one of them. At the time of compiling the EXE, the program does not know much about the AI classes other than what functions it must have.
Simplification:
basic class:
In other words: I want to create a card playing program, and I want the program to look for all different versions of AI it can find and use one of them. At the time of compiling the EXE, the program does not know much about the AI classes other than what functions it must have.
Simplification:
basic class:
Code:
class CAi : public CObject
{
public:
virtual CCard * PlayCard() = 0;
CAi()
virtual ~CAi();
}
[\code]
Sample derived AI class:
[code]
class CAiDumb : public CAi
{
public:
CCard * PlayCard(); // implemented in the AiDumb.cpp file
AFX_EXT_CLASS CAi * GetPlayer();
CAi()
virtual ~CAi();
}
[\code]
where:
[code]
CAi * CAiDumb::GetPlayer()
{
return new CAiDumb;
}
[\code]
Now, here is a tricky part:
The card playing program does not know about the class CAiDumb AT ALL before it compiles. CAiDumb is compiled inside a MFC DLL and exports the GetPlayer function as @1 (in the .DEF file).
Then the program uses ::AfxLoadDll to dynamically load the DLL containing the CAiDumb class. Then it uses the GetPlayer() function exported by the DLL to create instances of CAi's which are really CAiDumb's
e.g.:
[code]
HINSTANCE hLib = ::AfxLoadLibrary(nomDll);
if (hLib)
{
GETPLAYER pFunc = (GETPLAYER) GetProcAddress(hLib, MAKEINTRESOURCE(1) );
if (pFunc)
{
CAi * player1 = new pFunc();
}
}
[\code]
where:
[code]
typedef CAi * (CALLBACK* GETPLAYER)();
[\code]
defines GETPLAYER.
Still following?
Now player1 can be used to play, as in
[code]
player1->PlayCard();
[\code]
will actually work, using the code from CAiDumb found in the DLL.
Everything looks fine for now.
The problem comes when I try to delete the player after the game.
*****************************************************************
[code]
delete player1;
[\code]
This gives me an "assertion Failed" error (more precisely: "Expression: pHead->nBlockUse == nBlockUse" ). (This happens at the very end of the ~CObject destructor, as I followed the code line by line until I could not pinpoint the problem further.)
I think that what the problem here is that, since the EXE doesn't know anything about CAiDumb (it never saw the .CPP file when compiling), it does not know how much memory it takes to instanciate, and some sanity test fails when the actual number of bytes freed does not match whatever value it thought it was using.
So my questions are:
- is that a critical problem? When I choose "Ignore" the assertion, the rest of the execution looks fine, and the debugger does not complain about memory leaks.
- if I can safely ignore this assertion failure, how can I make the release version not show the Assertion Failed message box? The entry for "assert" in the MSVC reference says that defining NDEBUG when compiling will make the compiler ignore the "assert" lines, but that does not work...
- do you know of a simpler way to create instances of dynamically declared classes?
Thank you very much if you can help me through this...
Vincent