函数当输入函数时,存储在全局变量中的指针被设置为0,并且在退出函数时返回到之前的状态

问题描述:

我喜欢编程作为一种爱好,因此我通常有很多乐趣会变得非常低。函数当输入函数时,存储在全局变量中的指针被设置为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://*.com/help/mcve)。 – giusti

+0

我认为先回答的人说得对。我需要将所有函数指针定义为__declspec(selectany)...但我不确定它会怎样... – Lory

,如果你在头文件中写

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