2017-01-22 30 views
-4

我喜歡編程作爲一種愛好,因此我通常有很多樂趣會變得非常低。函數當輸入函數時,存儲在全局變量中的指針被設置爲0,並且在退出函數時返回到之前的狀態

在過去的幾天裏,我學習了Windows API,如何設置窗口,打開窗口並管理消息隊列。

渲染我決定使用OpenGL,並開始學習它。如果不使用像GLEW這樣的庫,它會自動加載所有必須手動完成的功能。

一切都很順利。我設法正確加載所有的函數指針,並將它們存儲在全局變量被任何人訪問,包括這個.h文件中:

#pragma once 

#include "glCoreARB.h" 
#include "wglExt.h" 

#define internal static 

extern "C" 
{ 
//FUNCTION POINTERS 
// Debug/Init Functions 
static PFNGLGETERRORPROC       glGetError; 
static PFNGLGETINTEGERVPROC      glGetIntegerv; 
static PFNGLGETSTRINGIPROC       glGetStringi; 
static PFNGLGETSTRINGPROC       glGetString; 

... AND MANY MORE (Not gonna write all of them down, you get it) 

//LOADING FUNCTIONS 
    internal void *GetAnyGLFuncAddress(const char *name) 
    { 
    void *p = (void *)wglGetProcAddress(name); 
    if ((p == 0) || (p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) || (p == (void*)-1)) 
    { 
     HMODULE module = LoadLibraryA("opengl32.dll"); 
     p = (void *)GetProcAddress(module, name); 
    } 

    return p; 
    } 

internal void LoadGLFunc(HDC DeviceContext) 
{ 
    glGetIntegerv = (PFNGLGETINTEGERVPROC)GetAnyGLFuncAddress("glGetIntegerv"); 
    glGetStringi = (PFNGLGETSTRINGIPROC)GetAnyGLFuncAddress("glGetStringi"); 
    glGetString  = (PFNGLGETSTRINGPROC)GetAnyGLFuncAddress("glGetString"); 
    glGetError  = (PFNGLGETERRORPROC)GetAnyGLFuncAddress("glGetError"); 

    GLint Version = getGLVersion(); 
    wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)GetAnyGLFuncAddress("wglGetExtensionsStringARB"); 
    const char *extensions = wglGetExtensionsStringARB(DeviceContext); 

    //Once I got the extensions I Loaded all of those function pointers 
    wglGetPixelFormatAttribivARB   = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)GetAnyGLFuncAddress("wglGetPixelFormatAttribivARB"); 

    ... And so on 

    //Then based on the available OpenGL Version 

    if (Version >= 33) 
    { 
     glGetShaderiv      = (PFNGLGETSHADERIVPROC)GetAnyGLFuncAddress("glGetShaderiv"); 
     glGetShaderInfoLog     = (PFNGLGETSHADERINFOLOGPROC)GetAnyGLFuncAddress("glGetShaderInfoLog"); 
     glGetProgramiv      = (PFNGLGETPROGRAMIVPROC)GetAnyGLFuncAddress("glGetProgramiv"); 
     glGetProgramInfoLog     = (PFNGLGETPROGRAMINFOLOGPROC)GetAnyGLFuncAddress("glGetProgramInfoLog"); 

    ... And many more... 

所有這些函數指針都是我的Windows平臺代碼中通過函數加載, ScreenInfo結構包含DeviceContext和,至此一切都事先檢索

internal VOID Win32_SetupOpenGLRenderingContext(ScreenInfo *Screen) 
{ 
PIXELFORMATDESCRIPTOR PixelFormat = {}; 

PixelFormat.nSize   = sizeof(PIXELFORMATDESCRIPTOR); 
PixelFormat.nVersion  = 1; 
PixelFormat.dwFlags   = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 
PixelFormat.iPixelType  = PFD_TYPE_RGBA; 
PixelFormat.cColorBits  = 32; //Colordepth of the framebuffer 
PixelFormat.cDepthBits  = 24; //Number of bits for the depthbuffer 
PixelFormat.cStencilBits = 8; //Number of bits for the stencilbuffer 

Screen->DeviceContext  = GetDC(Screen->WindowHandle); 
s32 PixelFormatValue  = ChoosePixelFormat(Screen->DeviceContext, &PixelFormat); 
SetPixelFormat(Screen->DeviceContext, PixelFormatValue, &PixelFormat); 

Screen->RenderingContext = wglCreateContext(Screen->DeviceContext); 
wglMakeCurrent(Screen->DeviceContext, Screen->RenderingContext); 

LoadGLFunc(Screen->DeviceContext); 
} 

現在WindowHandle 完美妝容的工作,所有的函數指針被正確加載,我可以打電話給所有的Windows裏面的GL功能平臺代碼。

但平臺的代碼,很明顯,調用應用程序的主循環裏它的消息循環:

while(Running) 
{ 
    MSG Msg; 
    while (PeekMessageA(&Msg, Screen.WindowHandle, 0, 0, PM_REMOVE)) 
    { 
     Win32_ProcessKeyboard(&Keyboard, Msg); 

     TranslateMessage(&Msg); 
     DispatchMessageW(&Msg); 

     if (Keyboard.isQuitting) 
     { 
      Running = FALSE; 
     } 
    } 

    Loop(&Screen); // THIS FUNCTION HERE! 

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 
    if (SwapBuffers(Screen.DeviceContext) == FALSE) 
    { 
     DWORD Error = GetLastError(); 
     LogError("In swapping buffers error: ", Error); 
    } 

} 

RIGHT進入循環功能一切正常了。這裏的循環功能代碼,這是在另一個文件:

extern "C" void GameLoop(ScreenInfo *Screen) 
{ 
    RenderTriangle(Screen); 

    return; 
} 

而且RenderTriangle電話:

internal void RenderTriangle(ScreenInfo *Screen) 
{ 
    GLuint shaderProgram; 
    GLuint VAO = 0; 

    if (Screen->wasTriangleInit == FALSE) 
    { 
    glViewport(0, 0, Screen->Width, Screen->Height); 

    glBindVertexArray(VAO); 

    GLfloat vertices[] = 
    { 
     -0.5f, -0.5f, 0.0f, 
     0.5f, -0.5f, 0.0f, 
     0.0f, 0.5f, 0.0f 
    }; 

    THERE IS MORE TO THIS FUNCTION, BUT THE PROBLEM HAPPENS WAY BEFORE, SO I'M PRETTY SURE IT'S IRRELEVANT. 

一旦我進入從平臺代碼迴路功能,ALL只有到了指針用在RenderTriangle CALL GET設置爲0x0

我試圖欺騙應用程序,通過添加如果(0){}上在任一切的頂框GL功能derTriangle調用,以避免崩潰,就像這樣:

internal void RenderTriangle(ScreenInfo *Screen) 
{ 
    GLuint shaderProgram; 
    GLuint VAO = 0; 
    if(0) 
    { 
    if (Screen->wasTriangleInit == FALSE) 
    { 
    glViewport(0, 0, Screen->Width, Screen->Height); 

    glBindVertexArray(VAO); 

    GLfloat vertices[] = 
    { 
     -0.5f, -0.5f, 0.0f, 
     0.5f, -0.5f, 0.0f, 
     0.0f, 0.5f, 0.0f 
    }; 

這樣,進入此功能時,所有的指針仍然可以設置爲0x0,但現在我站出來,重新進入Windows平臺的文件,所有函數指針被重新設置爲適當的值

我真的不知道該做什麼或發生了什麼。任何幫助?

+3

這是你想在你的信息清楚一件好事。但這只是太多的代碼。我建議你寫一個[小程​​序,重現你正在嘗試修復的錯誤](http://stackoverflow.com/help/mcve)。 – giusti

+0

我認爲先回答的人說得對。我需要將所有函數指針定義爲__declspec(selectany)...但我不確定它會怎樣... – Lory

回答

1

,如果你在頭文件中寫

static PFNGLGETERRORPROC       glGetError; 

c/cppglGetError自己的私人副本,因爲它static它不與其他衝突 - 所以不同cpp文件使用的glGetError不同的版本 - 在一個CPP裝置你初始化一個版本,它!!0,當你進入另一個cpp單元時 - 你使用了uninit版本,當它返回到原始單元時,它就是0。= 0; 所以與聲明不好的問題。

你需要聲明爲

extern PFNGLGETERRORPROC glGetError; 

.h文件和

PFNGLGETERRORPROC glGetError;

在任何單一CPP。文件。

或聲明爲

__declspec(selectany) PFNGLGETERRORPROC glGetError; 
+0

我已經將整個.h文件包裝在extern「C」{}塊中。問題是,如果我不使它們成爲靜態的,那麼鏈接器會抱怨它有這些函數的多個定義...但是__declspec(selectany)對我來說工作,它究竟幹嘛呢? – Lory

+0

@Lory - 你明白我的答案了嗎? '如果我不使它們成爲靜態的,那麼鏈接器就會抱怨它有這些函數的多個定義 - 關於這個我完全和寫。你有**這些函數的多個定義**。 'static static'關鍵字可以避免錯誤,但是可以將名稱設爲私有,但是您仍然擁有**這些函數的多個定義**,而且這個問題完全沒有關於'winapi'的問題 - 清除'c/C++'問題。 '__declspec(selectany)做什麼'?你嘗試搜索[它](https://msdn.microsoft.com/en-us/library/5tkz6s71.aspx)在谷歌? – RbMm

相關問題