函数当输入函数时,存储在全局变量中的指针被设置为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平台的文件,所有函数指针被重新设置为适当的值。
我真的不知道该做什么或发生了什么。任何帮助?
,如果你在头文件中写
static PFNGLGETERRORPROC glGetError;
每c/cpp
有glGetError
自己的私人副本,因为它static
它不与其他冲突 - 所以不同cpp
文件使用的glGetError
不同的版本 - 在一个CPP装置你初始化一个版本,它!!0,当你进入另一个cpp单元时 - 你使用了uninit版本,当它返回到原始单元时,它就是0。= 0; 所以与声明不好的问题。
你需要声明为
extern PFNGLGETERRORPROC glGetError;
在.h
文件和
PFNGLGETERRORPROC glGetError;
在任何单一CPP。文件。
或声明为
__declspec(selectany) PFNGLGETERRORPROC glGetError;
我已经将整个.h文件包装在extern“C”{}块中。问题是,如果我不使它们成为静态的,那么链接器会抱怨它有这些函数的多个定义...但是__declspec(selectany)对我来说工作,它究竟干嘛呢? – Lory
@Lory - 你明白我的答案了吗? '如果我不使它们成为静态的,那么链接器就会抱怨它有这些函数的多个定义 - 关于这个我完全和写。你有**这些函数的多个定义**。 'static static'关键字可以避免错误,但是可以将名称设为私有,但是您仍然拥有**这些函数的多个定义**,而且这个问题完全没有关于'winapi'的问题 - 清除'c/C++'问题。 '__declspec(selectany)做什么'?你尝试搜索[它](https://msdn.microsoft.com/en-us/library/5tkz6s71.aspx)在谷歌? – RbMm
这是你想在你的信息清楚一件好事。但这只是太多的代码。我建议你写一个[小程序,重现你正在尝试修复的错误](http://stackoverflow.com/help/mcve)。 – giusti
我认为先回答的人说得对。我需要将所有函数指针定义为__declspec(selectany)...但我不确定它会怎样... – Lory