Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 手动检索和存储指向OpenGL函数的指针时出现问题_C++_Linux_Windows_Opengl_Graphics - Fatal编程技术网

C++ 手动检索和存储指向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

我在手动检索和存储指向OpenGL函数的指针时遇到一些问题,下面是我代码的“简化片段”版本:

#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 )); 
    //...
}