Using A Namespace In Place Of A Class - c++

I'm designing an interface to abstract the tasks of managing Direct3D, Direct2D, DXGI, and the associated Win32API calls.
Keep everything inside a namespace or refactor to use a class?
WindowsApp.h
#pragma once
#include <Windows.h>
namespace WindowsApp
{
bool Initialize(HINSTANCE instanceHandle);
}
WindowsApp.cpp
#include "WindowsApp.h"
namespace WindowsApp
{
namespace
{
HWND ghMainWnd = 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
default:
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
}
bool Initialize(HINSTANCE instanceHandle)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"BasicWndClass";
if (!RegisterClass(&wc))
{
MessageBox(0, L"RegisterClass FAILED", 0, 0);
return false;
}
ghMainWnd = CreateWindow(
L"BasicWndClass",
L"Win32Basic",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
instanceHandle,
0);
if (ghMainWnd == 0)
{
MessageBox(0, L"CreateWindow FAILED", 0, 0);
}
ShowWindow(ghMainWnd, 1);
UpdateWindow(ghMainWnd);
return true;
}
}
Main.cpp
#include "WindowsApp.h"
int Run()
{
MSG msg = { 0 };
BOOL bRet = 1;
while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
{
if (bRet == -1)
{
MessageBox(0, L"GetMessage FAILED", L"Error", MB_OK);
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Deinitialize Here
return (int)msg.wParam;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
{
if (!WindowsApp::Initialize(hInstance)) { return 0; }
return Run();
}
Using a namespace allows me to hide implementation details inside the nested unnamed namespace.
A class wont let me hide things but I can make them inaccessible inside the private section, that's good enough I suppose.
Using a class runs the risk of users trying to instantiate multiple objects, which, would cause the application to crash from initializing DirectX twice or something.
Namespaces avoid this issue however they present a performance degrading factor, I have to check the Initialized variable during each function call. I really dislike this.
Finally using a class requires the user to pass around the instantiated object throughout the application wherever the underlying methods are needed. That is really disappointing since the namespace approach gives me access whenever I'm inside a file that's got an #include to the namespaces header file. I really like this.
The namespace approach seems like the best way to go but something doesn't quite sit right with me in the way variables are handled inside the nested unnamed namespace. Is that an okay practice? My gut is telling me no! no! no!
So I guess my question would be: Is this an appropriate use-case for namespaces?
For Clarification:
I've got the unnamed namespace defined inside WindowsApp.cpp along with the function definitions - forward declarations to all the functions are inside WindowsApp.h - Through use of calling these functions manipulates the variables inside the unnamed namespace. Is this a bad use of namespaces or should it be done a different way? Simply including the header file in any other .cpp gives you access to the functions and in turn the underlying data. This is very appealing. My gut tells me there is some kind of performance penalty that will ensue from structuring like this.

[EDIT: Remove stuff about unnamed namespaces begin unique to TUs now the code in the question has been clarified.]
In C++ we tend to think of a class as being a wrapper for some data which maintains an invariant (as opposed to a struct, which tends to be used for a bunch of data with no invariant). The constructor establishes the invariant, the destructor tears it down, and the member functions are careful to maintain it. Here, if I've understood correctly, it seems like your invariant is that Initialized() must called prior to using any other API function.
There is another alternative, which is to use so-called "magic statics", otherwise known as "Meyers singletons". Do something like the following:
// In WindowsApp.cpp
namespace {
class WindowsAppImpl {
public:
WindowsAppImpl()
{
// Do initialization stuff here
}
~WindowsAppImpl()
{
// Do teardown stuff if necessary
}
// Example function
int getMagicNumber()
{
return 3;
}
};
WindowsAppImpl& GetInstance() {
static WindowsAppImpl instance{};
return instance;
}
} // end private namespace
// Public function declared in WindowApp.h
int GetMagicNumber() {
// Get the singleton instance
WindowsAppImpl& instance = GetInstance();
// Call member function
return instance.getMagicNumber();
}
This approach adds a function which returns a reference to the singleton WindowsAppImpl instance. The compiler guarantees that this instance is constructed exactly once, the first time GetInstance() is called. (It will also run the destructor for WindowsAppImpl after main() has finished, which is probably not important in this case but can be useful in some cases.) The advantage of this approach is that inside GetMagicNumber() you can be sure the initialization routines have been run, without requiring the user to pass around some sort of WindowsAppContext instance of their own.

Related

How can i implement CreateThread - LPTHREAD_START_ROUTINE type ThreadProc callback function inside a C++ Class

Happy new year!
This is my baby steps in C++ world.
I used an example from learn.microsoft.com to create an example Win32 Console project which uses the WaitForMultipleObjects function to persist until all worker threads have terminated. All worked great!
Things get complicated (argument of type DWORD (Thread::*)(LPVOID lpParam) is incompatible with parameter of type "LPTHREAD_START_ROUTINE")
when i start to try to port the functionality of the concept inside a class which is similar like this:
class Threads
{
private:
HANDLE comThreads[1];
DWORD WINAPI closeThreadProc(LPVOID lpParam)
{
// lpParam not used in this example.
UNREFERENCED_PARAMETER(lpParam);
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
closeThreadProc, // Close thread function
NULL, // no thread parameters
0, // default startup flags
&dwThreadID);
}
public:
void Init()
{
CreateThreads();
}
}
I will try to use this class to create a Dynamic-link library(DLL).
While i am searching the answer to my own question.
I would like to ask you:
Is this even possible?
If it is possible. How can i achieve this, without loosing the underlying concept?
Thank you!
Edit:
Sorry for forgetting to tell if is it possible to make this, without making DWORD WINAPI closeThreadProc(LPVOID lpParam) static!
I did try to make it static before i posted the Question and things became even more wild (I barely forced to make everything in the class static).
I think this is the C++'s way to punish a rookie.
The LPVOID argument is there for a reason. The trick is to make the callback a static member but pass this as the extra parameter. You can then cast the LPVOID argument back to your object and call the method you want to. Some code will make it clearer
static DWORD WINAPI closeThreadProcCallback(LPVOID lpParam)
{
return static_cast<Threads*>(lpParam)->closeThreadProc();
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
closeThreadProcCallback, // Close thread callback function
this, // this object is the thread parameter
0, // default startup flags
&dwThreadID);
}
EDIT added WINAPI as suggested by Tomer W.
a threadStartfunction cant be _thiscall, and have to be _stdcall,
therefore i'd declare a static private method to pass your call to your object, i use the lpParameter to pass the object to the static function.
class Threads
{
private:
HANDLE comThreads[1];
static DWORD WINAPI staticThreadProc(LPVOID lpParam)
{
Threads& callingThread = *reinterpret_cast<Threads*>(lpParam);
return callingThread.closeThreadProc();
}
DWORD closeThreadProc()
{
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
staticThreadProc, // Close thread function
this, // no thread parameters
0, // default startup flags
&dwThreadID);
}
public:
void Init()
{
CreateThreads();
}
}

How to use SetTimer replace Sleep()?

I have a application that needs do something step by step, serially, like this:
...
func1();
Sleep(2000);
func2();
Sleep(3000);
func3();
...
As we know, calling Sleep() will cause the user interface to "freeze", so for example there is no response when trying to move the application window.
So, I tried using SetTimer() instead, as it seems that it would not cause the UI to freeze, but my question is how can I implement the same "waiting" function as Sleep() when using SetTimer()?
...
func1();
SetTimer(hwnd, ID_Timer2s,2000, Timerfunc2s);// how to make sure 2seconds waiting happen between func1 and func2?
func2();
SetTimer(hwnd, ID_Timer3s,3000, Timerfunc3s);
func3();
...
// my intention is kill the timer once timeout, then go back next func2(), how?
VOID CALLBACK Timerfunc2s(
HWND hwnd,
UINT message,
UINT idTimer,
DWORD dwTime)
{
KillTimer(hwnd, ID_Timer2s);
}
VOID CALLBACK Timerfunc3s(
HWND hwnd,
UINT message,
UINT idTimer,
DWORD dwTime)
{
KillTimer(hwnd, ID_Timer3s);
}
Thanks for any suggestions.
You want to run func2() only after ID_Timer2s expires, so run it when ID_Timer2s expires. Don't run it immediately.
...
func1();
SetTimer(hwnd, ID_Timer2s,2000, Timerfunc2s);
...
VOID CALLBACK Timerfunc2s(
HWND hwnd,
UINT message,
UINT idTimer,
DWORD dwTime)
{
KillTimer(hwnd, ID_Timer2s);
func2();
SetTimer(hwnd, ID_Timer3s,3000, Timerfunc3s);
}
VOID CALLBACK Timerfunc3s(
HWND hwnd,
UINT message,
UINT idTimer,
DWORD dwTime)
{
KillTimer(hwnd, ID_Timer3s);
func3();
}
As pointed out in the comments, this is not usually an appropriate design for a GUI application.
However, it can be appropriate for some very simple applications, e.g., those that perform a task that requires no user interaction, with a GUI that does nothing but provide feedback as to the progress of the task.
In such cases, and assuming that the code is not being called in the context of a window procedure, something like this should work:
...
func1();
MySleep(hwnd, 2000);
func2();
MySleep(hwnd, 3000);
func3();
...
BOOL MySleepTimerFlag;
void MySleep(HWND hwnd, DWORD timeout)
{
MySleepTimerFlag = FALSE;
SetTimer(hwnd, ID_MySleepTimer, timeout, MySleepTimerFunc);
while (MySleepTimerFlag == FALSE)
{
if (!GetMessage(&Msg, NULL, 0, 0)) fail();
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
VOID CALLBACK MySleepTimerFunc(
HWND hwnd,
UINT message,
UINT idTimer,
DWORD dwTime)
{
MySleepTimerFlag = TRUE;
KillTimer(hwnd, ID_MySleepTimer);
}
Note that this code was written off the cuff; I haven't attempted to compile it, never mind test it. But it should at least give you the idea.
Also, note that you can eliminate the global if it upsets you - attach a pointer as a window property or suchlike - but again, globals aren't really all that bad when used in very simple applications. :-)
Finally, the proviso that the call to MySleep() must not be in the context of a window procedure is important. That means that the first part of the code above must not, for example, be triggered by selecting a menu item. If it is, then you must use the approach outlined in Raymond's answer instead, or create a new thread as David suggested.
... also, as Raymond pointed out, you have to be careful that the GUI doesn't have any modal elements such as menus or dialog boxes, or at least that they are disabled while this code is running.
There are (at least) 3 options to do what you want. The first, using timers, Raymond Chen covered. The second, using a customized wait function, Harry Johnston covered. The third option is to create a thread, and do the work using that thread.
For example:
DWORD WINAPI ThreadProc(LPVOID lpThreadParameter)
{
func1();
Sleep(2000);
func2();
Sleep(3000);
func3();
...
return 0;
}
...
DWORD threadId = 0;
HANDLE hThread = CreateThread(NULL, 255, &ThreadProc, NULL, 0, &threadId);
The trouble comes when you need to interact with the UI. You can't directly do things to the UI from the alternate thread, but one technique you can use is to post messages to your UI and/or use shared state variables to affect the behavior of your UI thread.
Of course, it also should go without saying that as soon as you introduce threading, you also introduce the potential for hard to diagnose bugs, like race conditions and deadlocks. If func1, func2 or funcN modify global state you will need to synchronize access, either through critical sections, or some other synchronization method.

OpenGL version too low when using ifstream

I'm writing some elements of an engine for a 2D roguelike. I'm at a part where I'd like to be able to open .pngs. (I'm doing things manually because I like to learn about these things.) So I have created a PngLoader class and am starting to do basic things with it, like ... opening the file. For some reason this breaks the OpenGL GLFunctionFinder class that does something similar to GLEW, except manually.
The GLFF basically crashes out the program when the OpenGL version is too low; this is expected behavior. (Probably a segfault on an unset function pointer. I could "fix" this by making it crash more gracefully, but who cares?) The GLFF works rather well generally, since my graphics card runs OpenGL 4.3 or so, but I did have it break a few days ago when the driver switched to the integrated graphics driver (that only does OpenGL version 1.1). That was fixed by changing some settings in the graphics dashboard.
So the issue that I'm having crop up today is appearing when I write something like this:
class ifcontainerclass {
std::ifstream fs;
};
/* other code */
int WINAPI WinMain(/* ... */) {
GLFunctionFinder ff;
ff.interrogateWindows();
ifcontainerclass ifcc;
/* GL code and main loop */
return 0;
}
... the OpenGL context gets stuck on version 1.1. If I change ifstream to fstream, I get the higher version context that I expect, and the issue goes away.
I'm also finding in my testing that if I comment out the GL code and main loop area, the problem again disappears. The "version too low" checks are done in GLFunctionFinder::interrogateWindows(), not in the later GL code, so the conditions are still being checked. (After some testing, I'm finding that commenting out the MSG structure is what's making the problem go away.)
My current belief is the compiler is doing some magic that causes Windows / Intel / NVidia to only issue OpenGL 1.1 contexts / connect to the wrong driver when ... I really don't know when. The issue appears really arbitrary.
I'm probably going to look into getting rid of the global HDC and global HGLRC I was using out of laziness, since I think the problem is associated with how things are being initialized / how the compiler arranges to have these things initialized, and pulling them out of global scope will let me inspect and control that process more effectively. I did this in the GLFunctionFinder by using a static void * GlobalAddr = this file-scoped pointer, casting that to GLFunctionFinder in the dummy window's WndProc, and having HDC and HGLRC be member variables of GLFunctionFinder, accessible through the pointer. I will probably try something similar in my main window; I've been needing to clean up the global scoped stuff anyway. The other thing I can do is run each version in a debugger and see where it diverges, although I'm reluctant to do that since debugging is not really set up properly in my IDE and I'm not looking forward to fixing that.
I think I can get by in the meantime by using fstream instead of ifstream, but I'm not comfortable with not understanding problems that are this strange, since it suggests some kind of instability I ought to be aware of before I have 10k lines of code that arbitrarily stops running and can only be fixed by changing what appears to be a completely unrelated thing somewhere else.
Questions:
What in the world is happening? What is the core issue here?
Why does changing ifstream to fstream fix the problem?
Why does commenting out the MSG struct fix the problem?
PS: NvOptimusEnablement = 0x00000001 did not fix the issue.
PPS: MinGW 4.9.2 in Qt (as an IDE, no Qt libraries) with CMake
Edit: After determining Qt's debugger works when -ggdb is passed to g++, I stepped through the code and found the PIXELFORMATDESCRIPTOR in GLFunctionFinder was not being assigned; I was assigning the properties to some random temporary variable and not the member variable, while ChoosePixelFormat was using the member variable. Since the context you get depends on the kind of pixel you specify, I was effectively requesting an indeterminate device context from Windows. The specifics of compilation determined what random junk got put in the PIXELFORMATDESCRIPTOR, and it just so happens that declaring an ifstream instead of an fstream puts the wrong random junk in that area.
The problem was fixed by adding something to the effect of this->pfd_ = pfd; to GLFunctionFinder's constructor after defining the temporary pfd.
Edit 2: To satisfy my understanding of what the "off-topic" flag means, I'll provide a minimum example of the core problem:
main.cpp:
#include <windows.h>
#include <sstream>
#include <GL/gl.h>
HDC h_dc;
HGLRC h_context;
LRESULT CALLBACK MainWndProc(_In_ HWND h_wnd,
_In_ UINT u_msg,
_In_ WPARAM w_param,
_In_ LPARAM l_param) {
switch(u_msg) {
case WM_CREATE: {
PIXELFORMATDESCRIPTOR pfd; // <-- This was the error source, (pfd not set to an
// accelerated format, but only sometimes)
// except in my code it was harder to see than
// this.
h_dc = GetDC(h_wnd);
int pfint = ChoosePixelFormat(h_dc, &pfd);
SetPixelFormat(h_dc, pfint, &pfd);
h_context = wglCreateContext(h_dc);
wglMakeCurrent(h_dc, h_context);
const unsigned char * version_string =
static_cast<const unsigned char *>(glGetString(GL_VERSION));
if(version_string[0] == '1' || version_string[0] == '2') {
std::stringstream ss;
ss << "OpenGL version (" << version_string << ") is too low";
MessageBox(NULL, ss.str().c_str(), "Error", MB_OK | MB_ICONERROR);
}
break;
}
case WM_DESTROY:
PostQuitMessage(EXIT_SUCCESS);
break;
default:
return DefWindowProc(h_wnd, u_msg, w_param, l_param);
}
return 1;
}
int WINAPI WinMain( HINSTANCE h_inst,
HINSTANCE h_previnst,
LPSTR cmd_str_in,
int cmd_show_opt) {
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_OWNDC;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = h_inst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MAINWIN";
wc.hIconSm = NULL;
RegisterClassEx(&wc);
HWND h_wnd = CreateWindowEx(0,
"MAINWIN",
"MCVE Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
h_inst,
NULL);
return EXIT_SUCCESS;
}
CMakeLists.txt:
project(mcve_pfd_problem)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} WIN32 ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} opengl32)
In case someone skips to the end, the problem is solved, but I don't know how I'm supposed to indicate that.
So, what I was actually seeing was the effect of undefined behavior due to default-initializing a struct, where the values contained in it were uninitialized:
class GLFunctionFinder {
PIXELFORMATDESCRIPTOR pfdarr_;
/* other code */
GLFunctionFinder();
setupContext();
/* other code */
}
GLFunctionFinder::GLFunctionFinder() {
/* other code */
PIXELFORMATDESCRIPTOR pfd = { /* things */ };
// Missing: pfdarr_ = pfd;
// pfdarr_ never gets set
}
GLFunctionFinder::setupContext() {
// Undefined behavior:
int px_format_default = ChoosePixelFormat(this->h_cd, &(this->pfdarr_));
/* other code */
}
This gave ChoosePixelFormat whatever junk was in pfdarr_. When I initially wrote this, it behaved as though there was no problem, because apparently the junk data "looked like" an accelerated pixel format type, and ChoosePixelFormat would give me an int format that yielded the OpenGL context I was after. It stayed like that for a while, because it just kept working.
Switching from fstream to ifstream changed some specifics about the way the compiler laid out / optimized the program, and the junk data in pfdarr_ changed to "look like" an unaccelerated format. This led to getting the wrong context, which led to failing the OpenGL version check. The story with commenting out the MSG struct and part of the event loop is basically the same: it just so happens the compiler emits something that yields the OpenGL context I want.
I was compiling the code I gave in Edit 2 last night, and it was giving me a 1.1 context. This morning, exact same code, no error; moved the MessageBox and found I'm getting a 4.3 context. Fun errors.

Thoughts on a different way to running a win32 event loop without WndProc?

Whilst messing around with multithreading, callbacks, win32 api functions, and other troublesome troubles, I received an idea event. (hehehe)
What if, instead of defining a global (or static when designing a class) callback function, I instead assigned DefWindowProc for lpfnWndProc when registering the window class, and then ran the whole event loop on a separate thread?
This way I don't have to hack around the this problem when implementing the callback in a class
and the main thread's execution continues, freeing you from that god-forsaken while loop, allowing you to do whatever, even open another window (yay!)
The "normal" way:
LRESULT CALLBACK WndProc(...)
{
... // process event information
return DefWindowProc(...);
}
int CALLBACK WinMain(...)
{
... // initialize whatever needs initializing :)
WNDCLASSEX wc;
...
wc.lpfnWndProc = WndProc;
... // register the class, create the window, etc...
MSG msg;
while(GetMessage(&msg, 0, 0, 0) != 0)
{
... // TranslateMessage(&msg) if you want/need it
DispatchMessage(&msg); // dispatches the message to WndProc
}
return static_cast<int>(msg.wParam);
}
My newfound awesome way:
DWORD WINAPI MyAwesomeEventLoop(void* data) // must be static in a class
{
... // do whatever you need with the data
MSG msg;
while(GetMessage(&msg, 0, 0, 0) != 0)
{
... // TranslateMessage(&msg) if you want/need it
... // process event information
// call PostQuitMessage(0) to leave the loop
}
return static_cast<DWORD>(msg.wParam);
}
int CALLBACK WndProc(...)
{
...
WNDCLASSEX wc;
...
wc.lpfnWndProc = DefWindowProc;
...
HANDLE threadHandle = 0;
// use "this" as the 4th parameter when implementing in a class
threadHandle = CreateThread(0, 0, MyAwesomeEventLoop, 0, 0, 0);
... // you are now free to do whatever you want! :)
// waits untill the thread finishes
// hopefully because PostQuitMessage(0) was called
WaitForSingleObject(threadHandle, INFINITE);
DWORD returnValue = 0;
GetExitCodeThread(threadHandle, &returnValue);
CloseHandle(threadHandle);
...
return static_cast<int>(returnValue);
}
What do you guys think?
GetMessage docs on MSDN:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx
Read the first sentence: "Retrieves a message from the calling thread's message queue."
The message queue for a window is tied to the thread it was created on. Since you created your window on the main thread, your event loop running on a new thread will just not receive any messages for that window. If you want to run the event loop on another thread, you will need to create the thread first, then create your window on that thread.
That doesn't really buy you anything, except now you have window class-specific event handling code in a generic event loop, which is plain ugly. If you need background work, use worker threads. Keep the GUI and the event reactor inside the main thread, and use callbacks as documented.
And if you have a class whose instances handle windows, you shouldn't make them global even in single-threaded code (or you will suffer painful refactoring in the future).

global pointers to objects will break program by access violation when accessing object attributes/methods through them

This is code for an OpenGL application i'm making. I have the following code that produces an access violation (notice: i've only posted the code relevant to the problem):
// file: myHeader.h
class MyClass{
int classAttribute;
public:
void myClassFunction();
bool CreateGLWindow();
friend LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
MyClass();
~MyClass();
}
//file: myHeader.cpp
bool MyClass::CreateGLWindow(){
WNDCLASS wc;
wc.lpfnWndProc = (WNDPROC) WndProc;
}
void MyClass::myClassFunction(){
// do stuff
}
MyClass::MyClass(void){
CreateGLWindow();
}
//file main.cpp
#include myHeader.h
MyClass *p;
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
if (p->classAttribute){
p->myClassFunction();
}
}
int main(){
MyClass obj;
p = &obj;
BOOL done=FALSE;
while(!done)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))// Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE;
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (obj.active) // Program Active?
{
if (obj.keys[VK_ESCAPE])
{
done=TRUE;
}
else // Not Time To Quit, Update Screen
{
DrawGLScene();
obj.Swap(); // Swap Buffers (Double Buffering)
}
}
if (obj.keys[VK_F1])
{
obj.keys[VK_F1]=FALSE;
if (!obj.changeScreenMode())
{
return 0; // Quit If Window Was Not Created
}
}
}
}
}
}
What i get is an access violation on the line p->classAttribute and debugging shows that the attributes and methods of p can't be evaluated.
Any help will be greatly appreciated.
The constructor seems to create the window and associate the WndProc before p is assigned (the next line of code)
MyClass obj;
p = &obj;
You could set MyClass * p = NULL; and then wrap the use of p in
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
if(p)
{
if (p->classAttribute){
p->myClassFunction();
}
}
Not sure how useful this will be, but I'll throw it out there anyways.
p is pointing to the address of obj. The access violation is most likely due to the fact that p is accessing obj outside of scope (thus obj is getting cleared from the stack), or you are stomping on obj's memory. This is the reason why obj cannot be assessed by the debugger.
I would recommend a couple of things to help with the problem.
0) Log the memory location that p is pointing to (use %p in printf/_snprintf), and log memory location at key points in objs lifecycle.
1) get yourself adplus (part of Debugging Tools for Windows) and run it in crash mode against your process.
2) Debug the output of adplus with your favourite debugger (mine in WinDbg).
If worst comes to worst turn on the memory page boundary options in windows which should crash the program at attempt to access protected memory locations. Of course grayDad's suggestion will prevent the crash by stopping the access of a NULL pointer... unless obj is corrupted, in which case the pointer is just pointed to messed up memory and it will still crash. Try his solution first. :)