C++ 手动检索和存储指向OpenGL函数的指针时出现问题
我在手动检索和存储指向OpenGL函数的指针时遇到一些问题,下面是我代码的“简化片段”版本:C++ 手动检索和存储指向OpenGL函数的指针时出现问题,c++,linux,windows,opengl,graphics,C++,Linux,Windows,Opengl,Graphics,我在手动检索和存储指向OpenGL函数的指针时遇到一些问题,下面是我代码的“简化片段”版本: #ifdef WIN32 #include <windows.h> #endif #include <GL/gl.h> class CGLManager { public: // Manager functions bool GetAnyGLFuncAddress( const char *_cName, void *_pFunc ); bool Lo
#ifdef WIN32
#include <windows.h>
#endif
#include <GL/gl.h>
class CGLManager
{
public:
// Manager functions
bool GetAnyGLFuncAddress( const char *_cName, void *_pFunc );
bool LoadFunctions( void );
// OpenGL functions
void (APIENTRY *glBegin)( GLenum mode );
void (APIENTRY *glEnd)( void );
void (APIENTRY *glVertex3f)( GLfloat x, GLfloat y, GLfloat z );
private:
#ifdef WIN32
HMODULE m_hLib; // opengl32.dll
#else
void *m_hLib; // libGL.so
#endif
};
我的经理一般是这样工作的:它首先检查游戏引擎使用的渲染器(软件、OpenGL或Direct3D),如果不是OpenGL,那么我们就不再继续了。否则,我们加载库(opengl32.dll
或libGL.so
),检查它是否良好(再次,如果失败,我们停止),检索并存储指向OpenGL函数的指针(glBegin
,glEnd
,glVertex3f
)使用LoadFunctions
方法,如果一切正常或出现问题,我们将返回
现在的问题是:GetAnyGLFuncAddress
方法成功检索OpenGL函数(换句话说,glBegin
将返回true,glarrandomMethodThatDontexist
将返回false),但出于某种原因,gGL.glBegin
(它是“朋友”)在LoadFunctions中,
不会得到更新,它将始终为NULL,从而导致崩溃
我已经在互联网和StackOverflow上搜索了几个小时,试图找到一个解决方案,但我还没有找到任何能给我解决这个问题的答案
在我在StackOverflow上找到的许多网站和答案中,很多人建议使用像GLEW这样的OpenGL加载库,甚至OpenGL wiki也推荐它但是,由于我工作的环境的性质,我不能使用这些库,也不能直接使用OpenGL函数,我知道我正在经历手动操作的痛苦过程,但我别无选择
感谢您的回答。
*gl*getprocadres
仅用于返回扩展功能的入口点地址。它不需要返回操作系统OpenGL ABI要求(OpenGL-1.1适用于Windows,OpenGL-1.2适用于Linux软件库(LSB)4,OpenGL-2.1适用于LSB-5)中的函数的地址
通常,如果程序二进制文件直接链接到API库(存根)(与使用在运行时动态加载API库(存根)的加载程序相反),使用*gl*GetProcAddress
检索作为操作系统OpenGL ABI契约一部分的函数是愚蠢的,因为这些函数无论如何都可以通过常规API库获得wglGetProcAddress
与OpenGL-1.1函数一起导出,正如glXGetProcAddress
与所有OpenGL-1.2函数(至少)一起导出一样,因此如果您的程序看到*GetProcAddress
函数,它也会看到其他OpenGL函数
通过GetProcAddress加载所有OpenGL符号的唯一原因是使用LoadLibrary加载opengl32.dll
,或使用dlopen加载libGL.so
<>这只是常见的,断了C++。代码>\u pFunc是一个无效*
。指针是值。更改\u pFunc
的值不会更改传入变量的值
您应该只返回指针(NULL表示故障条件),或者\u pFunc
应该是void**
。不过,这可能需要调用方进行强制转换,GetAnyGLFuncAddress
需要执行*\u pFunc=
来设置值
如果要返回函数指针,则需要在存储它之前将返回的void*
强制转换为适当的函数指针类型。这就是为什么您经常看到OpenGL加载程序使用typedefs作为函数指针类型
typedef void (APIENTRY *(PFN_GLBEGIN))( GLenum );
...
PFN_GLBEGIN glBegin;
...
glBegin = static_cast<PFN_GLBEGIN>(GetAnyGLFuncAddress("glBegin"));
typedef void(apitery*(PFN_GLBEGIN))(格伦);
...
PFN_GLBEGIN GLBEGIN;
...
glBegin=static_cast(GetAnyGLFuncAddress(“glBegin”);
忘记你的最终目标是什么,我看到了基本的C++错误。 让我们删掉所有与此无关的代码,并将重点放在以下方面:
bool CGLManager::GetAnyGLFuncAddress( const char *_cName, void *_pFunc )
{
_pFunc = (void *)wglGetProcAddress( _cName ); // <-- This sets the local pointer
//...
}
您正在第二个参数中传递地址,但在函数GetAnyGLFuncAddress
中,您没有更新该值,以便将新值反射回调用方。您正在设置本地值,因此将不会设置gGL.glBegin
(以及其他两个调用中的所有其他地址)
在GetAnyGLFuncAddress
中,我本以为这会起作用:
bool CGLManager::GetAnyGLFuncAddress( const char *_cName, void *_pFunc )
{
*_pFunc = (void *)wglGetProcAddress( _cName ); // <-- Note the *
//...
}
由于类型现在是
FnPtr*
,因此您传入的任何内容都将自动具有该类型的FnPtr
。不再使用void*
(除了wglGetProcAddress
的返回值,它是强制转换的)。忘记openGL等。如果在GetAnyGLFuncAddress
中更新pFunc
(实际上是一个本地临时值),该函数将如何工作?您设置的pFunc
值不会反映回调用者。我希望*pFunc=whatever
,而不是pFunc=whatever
,也就是说,您应该取消引用该指针值。“但是,由于我工作的环境的性质,我不能使用这些库”。。。这确实是一个非常奇怪的环境,其中不能包含.h文件和.cpp文件。有些加载程序没有其他加载程序复杂。@PaulMcKenzie将星号放在\u pFunc
之前会导致C2100错误(非法间接寻址)@Shepard62700FR:这不是论坛。答案在答案部分。你不能编辑你的问题,说它已经解决了。@Nicolas抱歉,不会再发生这种情况了。编写了几个OpenGL加载程序,如果在每个平台上都能运行相同的程序,那么加载代码就简单多了。您不必根据所使用的平台在函数声明和函数指针声明之间进行选择;一切都是函数指针。你的加载器就可以
bool CGLManager::GetAnyGLFuncAddress( const char *_cName, void *_pFunc )
{
_pFunc = (void *)wglGetProcAddress( _cName ); // <-- This sets the local pointer
//...
}
bool CGLManager::LoadFunctions( void )
{
if ( !(GetAnyGLFuncAddress( "glBegin", &gGL.glBegin )) )
return false;
}
bool CGLManager::GetAnyGLFuncAddress( const char *_cName, void *_pFunc )
{
*_pFunc = (void *)wglGetProcAddress( _cName ); // <-- Note the *
//...
}
template <typename FnPtr>
bool CGLManager::GetAnyGLFuncAddress( const char *_cName, FnPtr* _pFunc )
{
*_pFunc = reinterpret_cast<FnPtr>(wglGetProcAddress( _cName ));
//...
}