Sign in to follow this  
Tarpedoe81

Book code error... need help!

Recommended Posts

Tarpedoe81    122
Hi. I'm a beginner and I bought the book, "Programming Roleplaying Games with DirectX", and I ran into a problem. I'm using Visual C++ Express 2008 and I'm using the System Core code from chapter 10. The problem is using the cStateManger class code and example. When it compiles it displays the first message box, but not the second. I've added breakpoints to each function in the class, and when it goes to each breakpoint, the Watch window displays "m_StateParent - CXX0017: Error: symbol "m_StateParent" not found", or "m_StateParent - CXX0069: Error: variable needs stack frame". I don't know why it diplays this and how to change it. And I thought Jim Adams is an expert programmer, lol. If anybody could help, please reply. Here's the code! Core_System.h: #ifndef SYSTEM_H #define SYSTEM_H class cApplication { private: HINSTANCE m_hInst; // Instance handle HWND m_hWnd; // Window handle protected: char m_Class[MAX_PATH]; // Class name char m_Caption[MAX_PATH]; // Window caption WNDCLASSEX m_wcex; // Windows class structure DWORD m_style; // Window style DWORD m_XPos; // X coordinate of window DWORD m_YPos; // Y coordinate of window DWORD m_Width; // Default width of window DWORD m_Height; // Default height of window public: cApplication(); // Constructor HWND GethWnd(); // Returns window handle HINSTANCE GethInst(); // Returns instance handle BOOL Run(); // Executes class code BOOL Error(BOOL Fatal, char *Text, ...); // Prints error BOOL Move(long XPos, long YPos); // Move window BOOL Resize(long Width, long Height); // Resize client area BOOL ShowMouse(BOOL Show = TRUE); // Show or hide cursor // Default message handler virtual long FAR PASCAL MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hWnd, uMsg, wParam, lParam); } // Custom functions that will hold your game code virtual BOOL Init() { return TRUE; } virtual BOOL Shutdown() { return TRUE; } virtual BOOL Frame() { return TRUE; } }; // Static pointer to class static cApplication *g_pApplication = NULL; // Message procedure static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // Calling purpose enum Purpose { NOPURPOSE = 0, INITPURPOSE, SHUTDOWNPURPOSE, FRAMEPURPOSE }; class cStateManager { // State function pointers (linked list) typedef struct sState { void (*Function)(void *Ptr, long Purpose); sState *Next; // Structure constructor that clears pointers sState() { Function = NULL; Next = NULL; } // Structure destructor to delete linked list ~sState() { delete Next; } } sState; protected: sState *m_StateParent; // State stack link list parent public: cStateManager(); // Constructor ~cStateManager(); // Destructor // Pushes a state on the stack, along with a user-defined pointer. // The push function will call the state function with an init purpose. void Push(void (*Function)(void *Ptr, long Purpose), void *DataPtr = NULL); // Pop top-most state off stack, calling it with a shutdown purpose. BOOL Pop(void *DataPtr = NULL); // Pop all states, calling SHUTDOWN purpose for each. void PopAll(void *DataPtr = NULL); // Process the top-most state with a frame purpose. BOOL Process(void *DataPtr = NULL); }; Core_System.cpp: #include "Core_Global.h" cApplication::cApplication() { // Save instance handle g_pApplication = this; // Get the instance handle m_hInst = GetModuleHandle(NULL); // Set a default window class and caption strcpy(m_Class, "AppClass"); strcpy(m_Caption, "Application Caption"); // Set default window style, position, width, height m_style = WS_OVERLAPPEDWINDOW; m_XPos = 0; m_YPos = 0; m_Width = 256; m_Height = 256; // Set default WNDCLASSEX structure m_wcex.cbSize = sizeof(WNDCLASSEX); m_wcex.style = CS_CLASSDC; m_wcex.lpfnWndProc = WindowProc; m_wcex.cbClsExtra = 0; m_wcex.cbWndExtra = 0; m_wcex.hInstance = m_hInst; m_wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); m_wcex.hCursor = LoadCursor(NULL, IDC_ARROW); m_wcex.hbrBackground = NULL; m_wcex.lpszMenuName = NULL; m_wcex.lpszClassName = m_Class; m_wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); } HWND cApplication::GethWnd() { return m_hWnd; } HINSTANCE cApplication::GethInst() { return m_hInst; } BOOL cApplication::Run() { MSG Msg; // Register window class if (!RegisterClassEx(&m_wcex)) return FALSE; // Create the Main Window m_hWnd = CreateWindow(m_Class, m_Caption, m_style, m_XPos, m_YPos, m_Width, m_Height, NULL, NULL, m_hInst, NULL); if (!m_hWnd) return FALSE; // Show and update the window ShowWindow(m_hWnd, SW_NORMAL); UpdateWindow(m_hWnd); // Make sure client area is correct size Resize(m_Width, m_Height); // Initialize COM CoInitialize(NULL); // Do application initialization - return on FALSE if (Init() == TRUE) { // Enter the message pump ZeroMemory(&Msg, sizeof(MSG)); while (Msg.message != WM_QUIT) { // Handle Windows messages (if any) if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } else { // Do per-frame processing, break on FALSE return value if (Frame() == FALSE) break; } } } // Do shutdown functions Shutdown(); // Shutdown COM CoUninitialize(); // Unregister the window class UnregisterClass(m_Class, m_hInst); return TRUE; } BOOL cApplication::Error(BOOL Fatal, char *Text, ...) { char CaptionText[12]; char ErrorText[2048]; va_list valist; // Build the message box caption based on fatal flag if (Fatal == FALSE) strcpy(CaptionText, "Error"); else strcpy(CaptionText, "Fatal Error"); // Build variable text buffer va_start(valist, Text); vsprintf(ErrorText, Text, valist); va_end(valist); // Display the message box MessageBox(NULL, ErrorText, CaptionText, MB_OK | MB_ICONEXCLAMATION); // Post a quit message if error was fatal if (Fatal == TRUE) PostQuitMessage(0); return TRUE; } BOOL cApplication::Move(long XPos, long YPos) { RECT ClientRect; GetClientRect(m_hWnd, &ClientRect); MoveWindow(m_hWnd, XPos, YPos, ClientRect.right, ClientRect.bottom, TRUE); return TRUE; } BOOL cApplication::Resize(long Width, long Height) { RECT WndRect, ClientRect; long WndWidth, WndHeight; GetWindowRect(m_hWnd, &WndRect); GetClientRect(m_hWnd, &ClientRect); WndWidth = (WndRect.right - (ClientRect.right - Width)) - WndRect.left; WndHeight = (WndRect.bottom - (ClientRect.bottom - Height)) - WndRect.top; MoveWindow(m_hWnd, WndRect.left, WndRect.top, WndWidth, WndHeight, TRUE); return TRUE; } BOOL cApplication::ShowMouse(BOOL Show) { ShowCursor(Show); return TRUE; } // The message procedure - empty except for destroy message LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0); break; default: return g_pApplication->MsgProc(hWnd, uMsg, wParam, lParam); } return 0; } cStateManager::cStateManager() { m_StateParent = NULL; } cStateManager::~cStateManager() { PopAll(); } // Push a function on to the stack void cStateManager::Push(void (*Function)(void *Ptr, long Purpose), void *DataPtr) { sState *StatePtr; // Don't push a NULL value if (Function != NULL) { // Allocate a new state and push it on stack StatePtr = new sState; m_StateParent = StatePtr; StatePtr->Next = m_StateParent; StatePtr->Function = Function; // Call state with init purpose StatePtr->Function(DataPtr, INITPURPOSE); } } BOOL cStateManager::Pop(void *DataPtr) { sState *StatePtr; // Remove the head of stack (if any) if ((StatePtr = m_StateParent) != NULL) { // First call with shutdown purpose m_StateParent->Function(DataPtr, SHUTDOWNPURPOSE); m_StateParent = StatePtr->Next; StatePtr->Next = NULL; delete StatePtr; } // return TRUE if more states exist, FALSE otherwise if (m_StateParent == NULL) return FALSE; return TRUE; } void cStateManager::PopAll(void *DataPtr) { while (Pop(DataPtr) == TRUE); } BOOL cStateManager::Process(void *DataPtr) { // return an error if no more states if (m_StateParent == NULL) return FALSE; // Process the top-most state m_StateParent->Function(DataPtr, FRAMEPURPOSE); return TRUE; } WinMain.cpp: #include "Core_Global.h" class cApp : public cApplication { private: cStateManager m_StateManager; // State function prototypes static void Function1(void *, long); static void Function2(void *, long); public: cApp(); // Constructor BOOL Init(); // Overloaded Init function BOOL Shutdown(); // Overloaded Shutdown function BOOL Frame(); // Overloaded Frame function }; void cApp::Function1(void *DataPtr, long Purpose) { // Get a pointer to the calling class, as this function is // static, meaning it's not assigned a class instance. cApp *cc = (cApp*)DataPtr; // Display a message on INIT and push a 2nd state if (Purpose == INITPURPOSE) { MessageBox(cc->GethWnd(), "State 1", "Message", MB_OK); cc->m_StateManager.Push(Function2, cc); return; } // Force program to exit if (Purpose == FRAMEPURPOSE) cc->m_StateManager.Pop(cc); } void cApp::Function2(void *DataPtr, long Purpose) { cApp *cc = (cApp*)DataPtr; // Display a message and pop itself if (Purpose == FRAMEPURPOSE) { MessageBox(cc->GethWnd(), "State 2", "Message", MB_OK); cc->m_StateManager.Pop(cc); return; } } cApp::cApp() { // Set up the window style, position, width, and height m_style = WS_OVERLAPPEDWINDOW; m_XPos = 0; m_YPos = 0; m_Width = 640; m_Height = 480; // Assign a class name and window caption strcpy(m_Class, "NameClass"); strcpy(m_Caption, "My Name Example"); } BOOL cApp::Init() { // Perform application initialization functions here // such as those that set up the graphics, sound, network, etc. // Return a value of TRUE for success, FALSE otherwise. m_StateManager.Push(Function1, this); return TRUE; } BOOL cApp::Shutdown() { // Perform application shutdown functions here // such as those that shut down the graphics, sound, etc. // Return a value of TRUE for success, FALSE otherwise. return TRUE; } BOOL cApp::Frame() { // Perform frame processing, such as rendering. // Return TRUE on success, FALSE otherwise. return TRUE; } // Entry point int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { cApp App; App.Run(); // Exit application return 0; } Core_Global.h: #ifndef GLOBAL_H #define GLOBAL_H // Windows includes #include <windows.h> // Standard ANSI-C includes #include <stdio.h> // Core includes #include "Core_System.h" #endif

Share this post


Link to post
Share on other sites
Gage64    1235
You have posted a very long code listing, most of which is irrelevant to your problem, and you didn't use source tags (read the FAQ if you don't know how), so it's pretty hard to guess the problem. To make it easier for us, step through the program with the debugger, see where the program starts misbehaving (for example, make sure that Function2() is indeed added to the state manager) and report back with more detailed information.

Also, where do you call Process()?

Share this post


Link to post
Share on other sites
dashurc    236
I did a quick look up on MSDN. It looks like error CXX0017 means the debugger is having problems resolving the name, since it can't properly type cast the variable. Change the following code from:

typedef struct sState
{
.
. code hidden for simplicity
.
} sState;



To:


struct sState
{
.
. code hidden for simplicity
.
};



since you're using C++ anyways.


I don't know why you'd be running into CX0069 though since it only mentions variables declared in inline functions. It may be because the variable is out of scope or not yet declared (although I don't get that message for either of those situations in my debugger...).



From MSDN:

Expression Evaluator Error CXX0069
variable needs stack frame

The expression evaluator cannot evaluate the variable because it does not occur in a stack frame. This may be caused by variables declared as part of an inline function.




Expression Evaluator Error CXX0017

Error Message
symbol not found


A symbol specified in an expression could not be found.

One possible cause of this error is a case mismatch in the symbol name. Because C and C++ are case-sensitive languages, a symbol name must be given in the exact case in which it is defined in the source.

This error can occur when trying to typecast a variable in order to watch the variable during debugging. The typedef declares a new name for a type, but it does not define a new type. The typecast attempted in the debugger requires the name of a defined type.

This error is identical to CAN0017.

To fix by using the following possible solutions
Make sure the symbol is already declared at the point in the program where it is being used.

Use an actual type name to cast variables in the debugger, rather than a typedef-defined name.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this