Ручная загрузка расширений OpenGL LNK2005 и LNK1169 - PullRequest
0 голосов
/ 22 марта 2019

Я использую Visual C ++ и вручную пытаюсь загрузить расширения OpenGL. Однако по какой-то причине определение указателей из предоставленных заголовков групп Khronos приводит к ошибкам компоновщика, и поэтому я никогда не получаю изменения даже для определения этих функций в моем контексте OpenGL. Ниже я включил упрощенную версию своего кода и его структуру, которая вызывает ту же проблему.

//Test.cpp
#include "MyGL.h"
#include <iostream>

int main()
{
    std::cout << "Hello World!\n"; 
}
//MyGL.h
#pragma once
#include "MyGLOpenGL.h"
//MyGL.cpp
#include "MyGL.h"
//MyGLOpenGL.h
#pragma once

#include <windows.h> // Windows functions
#include <GL/gl.h> // Provided w/ Compiler
#include "GL/glext.h" // Put out by Khronos Group
#include "GL/wglext.h" // Put out by Khronos Group
#pragma comment(lib, "opengl32.lib") // Provided w/ Compiler



#ifndef GL_OPENGL
#define GL_OPENGL

void glInitPointers(); // Defines pointers to opengl functions
void* glGetAnyProcAddress(const char* name); // Gets a pointer to any OpenGL function

extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
#endif

//MyGLOpenGL.cpp
#include "MyGLOpenGL.h"

void glInitPointers() {
    wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glGetAnyProcAddress("wglChoosePixelFormatARB"); //load function
    wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)glGetAnyProcAddress("wglCreateContextAttribsARB"); //load function
    return;
}

void* glGetAnyProcAddress(const char* name) {
    void *pointer = (void *)wglGetProcAddress(name);
    if (pointer == 0 || (pointer == (void*)0x1) || (pointer == (void*)0x2) || (pointer == (void*)0x3) || (pointer == (void*)-1)) {
        HMODULE module = LoadLibraryW(L"opengl32.dll");
        pointer = (void *)GetProcAddress(module, name);
    }
    return pointer;
};

Компиляция этого дает мне следующие ошибки компоновщика:

1>MyGLOpenGL.obj : error LNK2001: unresolved external symbol "int (__stdcall* wglChoosePixelFormatARB)(struct HDC__ *,int const *,float const *,unsigned int,int *,unsigned int *)" (?wglChoosePixelFormatARB@@3P6GHPAUHDC__@@PBHPBMIPAHPAI@ZA)
1>MyGLOpenGL.obj : error LNK2001: unresolved external symbol "struct HGLRC__ * (__stdcall* wglCreateContextAttribsARB)(struct HDC__ *,struct HGLRC__ *,int const *)" (?wglCreateContextAttribsARB@@3P6GPAUHGLRC__@@PAUHDC__@@PAU1@PBH@ZA)
1>G:\Development\Test\Debug\Test.exe : fatal error LNK1120: 2 unresolved externals

Поскольку проблема заключалась в нерешенных внешних символах, я попытался удалить ключевое слово extern, чтобы вместо этого получить следующие две ошибки:

1>MyGLOpenGL.obj :error LNK2005: "int (__stdcall* wglChoosePixelFormatARB)(struct HDC__ *,int const *,float const *,unsigned int,int *,unsigned int *)" (?wglChoosePixelFormatARB@@3P6GHPAUHDC__@@PBHPBMIPAHPAI@ZA) already defined in MyGL.obj
1>MyGLOpenGL.obj : error LNK2005: "struct HGLRC__ * (__stdcall* wglCreateContextAttribsARB)(struct HDC__ *,struct HGLRC__ *,int const *)" (?wglCreateContextAttribsARB@@3P6GPAUHGLRC__@@PAUHDC__@@PAU1@PBH@ZA) already defined in MyGL.obj
1>Test.obj : error LNK2005: "int (__stdcall* wglChoosePixelFormatARB)(struct HDC__ *,int const *,float const *,unsigned int,int *,unsigned int *)" (?wglChoosePixelFormatARB@@3P6GHPAUHDC__@@PBHPBMIPAHPAI@ZA) already defined in MyGL.obj
1>Test.obj : error LNK2005: "struct HGLRC__ * (__stdcall* wglCreateContextAttribsARB)(struct HDC__ *,struct HGLRC__ *,int const *)" (?wglCreateContextAttribsARB@@3P6GPAUHGLRC__@@PAUHDC__@@PAU1@PBH@ZA) already defined in MyGL.obj
1>G:\Development\Test\Debug\Test.exe : fatal error LNK1169: one or more multiply defined symbols found

Я также уже удостоверился, что "#pragma Once" был в любом файле, защита заголовков, добавление "OpenGL32.lib" в дополнительные зависимости в Visual Studio, добавление комментария прагмы для lib, установка равных указателей обнулить в объявлении, и я просто в полном недоумении, чтобы попробовать что-то еще, даже после поиска проблемы. И в моем случае, используя GLEW или любую другую библиотеку загрузки расширений, потому что это именно то, что я пытаюсь создать.

Ответы [ 2 ]

2 голосов
/ 22 марта 2019

В C и C ++ есть важное различие между объявлением и определением . Выписка в форме

extern <type> <symbol>;

заявляет , что где-то есть символ , но на самом деле он не приводит его к существованию. Это больше похоже на обещание компилятору, что символ будет определен где-то еще. Когда ты написал

extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;

вы фактически не создавали переменные для этих указателей на функции, вы просто "перечислили их в оглавлении" для своей программы. Вы на самом деле должны определить их где-то. То есть в каком-то модуле компиляции вы должны написать (без внешнего).

PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;

Это не имеет абсолютно никакого отношения к инициализации, как намекнул @EricLopushansky; все дело в том, что они действительно определены. Так как это глобальная область, они все равно будут инициализированы в 0, даже если вы явно не напишите это = 0.

0 голосов
/ 22 марта 2019

Это не очень хорошо объясняется вики OpenGL в статье Загрузка функций OpenGL , но просто выполните следующее.Установка указателя на ноль в файле cpp решит проблему.Например:

PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;

Для всех, кто заинтересован, вот соответствующий код от GLEW, который служит той же цели:

//glew.h
#ifdef GLEW_STATIC
#  define GLEWAPI extern
#else
#  ifdef GLEW_BUILD
#    define GLEWAPI extern __declspec(dllexport)
#  else
#    define GLEWAPI extern __declspec(dllimport)
#  endif
#endif
#define GLEW_FUN_EXPORT GLEWAPI

//wglew.h
#define WGLEW_GET_FUN(x) x
#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB)
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#define WGLEW_FUN_EXPORT GLEW_FUN_EXPORT
WGLEW_FUN_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;

//glew.c
#  define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name)
PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL;
r = ((wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")) == NULL) || r;


//I would be using this static so it would evaluate in my code to
//MyGLOpenGL.h
#define wglChoosePixelFormatARB __wglewChoosePixelFormatARB
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
extern PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;

//MyGLOpenGL.cpp
PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL;
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...