Seemingly Random LNK2005 Errors With GLFW3 - c++

I'm getting the error LNK2005 for seemingly no reason, or at least none that can I can identify. Essentially, using the following code I can compile without issue.
test.h
#define GLEW_STATIC
#include <GL\glew.h>
#include <GLFW\glfw3.h>
namespace test
{
//Objects and variables
GLFWwindow* window;
//Function prototypes
bool Initialize();
}
test.cpp
#include "test.h"
#include <iostream>
bool test::Initialize()
{
std::cout << "Initializing GLFW: OpenGL version 3.3 \n";
//Initialize GLFW
glfwInit();
//Set window properties (version 3.3, core profile, not resizeable)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//Create Window
window = glfwCreateWindow(800, 800, "Learn OpenGL", nullptr, nullptr);
if (window = nullptr)
{
std::cout << "Failed to create GLFW window \n";
glfwTerminate();
return false;
}
return true;
}
int main()
{
test::Initialize();
return 0;
}
However, when compiling nearly the exact same thing (http://pastebin.com/VpPep9pM), along with some other code, it gives the errors:
Error LNK2005 "struct GLFWwindow * window" (?window##3PAUGLFWwindow##A) already defined in Main.obj OpenGL D:\Users\Matthew\documents\visual studio 2015\Projects\OpenGL\OpenGL\System.obj
Error LNK2005 "struct GLFWwindow * System::window" (?window#System##3PAUGLFWwindow##A) already defined in Main.obj OpenGL D:\Users\Matthew\documents\visual studio 2015\Projects\OpenGL\OpenGL\System.obj
Error LNK1169 one or more multiply defined symbols found OpenGL D:\Users\Matthew\documents\visual studio 2015\Projects\OpenGL\Debug\OpenGL.exe
So, I would like to know what causes the errors, I'm assuming it has something to do with the "context".

In your header file, you are defining you variable, when it needs to be declared in the header and defined in one source file.
In test.h
namespace test {
extern GLFWwindow* window;
}
and in main.cpp
namespace test {
GLFWwindow* window;
}
Without the extern in the header, you create one instance of test::window in every source file that includes it, which is a problem if there are two or more definitions.

Related

Avoid ambiguity in C++

I am trying to implement a C++ wrapper alongside my C project.
So, for example, I have "window.h" which has the standard C include guard. It requires <stdlib.h> and <string.h> as well as some third party library includes.
Then, I have "window.hpp" which depends on "window.h", but uses C++ #pragma once and requires <cstdlib> and <string> for the C++ implementations.
I am running into an ambiguity issue where the C/C++ standard implementations are conflicting, and I'm not quite sure what to do about it. You can see I tried to fix this by simply checking if __cplusplus was defined, and only adding the C++ headers if that's the case.
The idea is that you can just do using namespace LittleEngine::utils; and it will include SDL and GLEW for you, as well as add some wrapper features for creating a window, for example; where it uses C++ features like classes instead of the C implemented methods.
For sanity's sake, that's why these are separate files and not just one header file that adds compatibility for both C and C++ with extern "C" { ... }.
"window.h"
#if __cplusplus
#pragma once
#endif
#ifndef LITTLE_ENGINE_UTILS_WINDOW_H_
#define LITTLE_ENGINE_UTILS_WINDOW_H_
#include <SDL2/SDL.h>
#include <GL/glew.h>
#if __cplusplus
# include <cstdio>
# include <string>
#else
# include <stdio.h>
# include <string.h>
#endif
typedef struct {
SDL_Window* window;
SDL_GLContext context;
SDL_Event event;
} Engine_GLWindow_t;
enum Engine_Window_Renderer {
VULKAN,
OPENGL
};
int Engine_CreateGLWindow(const char* title, Engine_GLWindow_t* window)
{
// Initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
fprintf(stderr, "Failed to initialize SDL.\n");
fprintf(stderr, "%s\n", SDL_GetError());
return -1;
}
// Configure window flags
Uint32 flags = 0;
flags |= SDL_WINDOW_OPENGL;
SDL_Window* sdlwin = SDL_CreateWindow(
title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
800,
600,
flags
);
if(!sdlwin)
return -1;
window->window = sdlwin;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
SDL_GL_SetSwapInterval(1);
SDL_GLContext context;
if((context = SDL_GL_CreateContext(window->window)) != NULL)
window->context = context;
else
{
SDL_DestroyWindow(window->window);
fprintf(stderr, "Failed to initialize the GL context.\n");
fprintf(stderr, "%s\n", SDL_GetError());
return -1;
}
glewExperimental = GL_TRUE;
GLenum glewCode = glewInit();
if(glewCode != GLEW_OK)
{
SDL_GL_DeleteContext(window->context);
SDL_DestroyWindow(window->window);
fprintf(stderr, "Failed to initialize GLEW.\n");
fprintf(stderr, "%s\n", glewGetErrorString(glewCode));
return -1;
}
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, 800, 600);
SDL_ShowWindow(sdlwin);
return 0;
}
int Engine_DestroyGLWindow(Engine_GLWindow_t* window)
{
SDL_GL_DeleteContext(window->context);
SDL_DestroyWindow(window->window);
SDL_Quit();
return 0;
}
#endif
"windows.hpp"
#pragma once
/*
file included as:
engine.hpp
...
namespace LittleEngine {
namespace utils {
# include "utils.hpp" // -> #include "windows.hpp"
}
}
*/
#include "window.h"
#include <cstdint>
class GLWindow {
public:
GLWindow(std::string title)
{
Engine_CreateGLWindow(title.c_str(), &this->window_data);
}
GLWindow(std::string title, bool& success)
{
if(Engine_CreateGLWindow(title.c_str(), &this->window_data) == 0)
success = true;
}
~GLWindow()
{
Engine_DestroyGLWindow(&this->window_data);
}
Engine_GLWindow_t* getWindowData()
{
return &this->window_data;
}
protected:
Engine_GLWindow_t window_data;
};
main.cpp
#include <LittleEngine/engine.hpp>
int main(int argc, char* argv[], char* envp[])
{
// COMMENTED CODE WORKS BTW
// Engine_GLWindow_t window;
// Engine_CreateGLWindow("LittleBird", &window);
LittleEngine::utils::GLWindow window("LittleBird");
bool should_run = true;
const LittleEngine::utils::Uint8* keys = nullptr;
while (should_run)
{
while (LittleEngine::utils::SDL_PollEvent(&window.getWindowData()->event))
if (window.getWindowData()->event.type == LittleEngine::utils::SDL_QUIT)
should_run = false;
// ensure that SDL2 updated the keyboard state
LittleEngine::utils::SDL_PumpEvents();
// // automatically update window size
// UpdateWindowSize(&window);
// SDL2 should automatically clear this memory after each loop
keys = LittleEngine::utils::SDL_GetKeyboardState(0);
// black background color
LittleEngine::utils::glClearColor(0.00f, 0.00f, 0.00f, 1.00f);
// red background color if pressing W
if(keys[LittleEngine::utils::SDL_SCANCODE_W])
LittleEngine::utils::glClearColor(1.00f, 0.00f, 0.00f, 1.00f);
LittleEngine::utils::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
LittleEngine::utils::SDL_GL_SwapWindow(window.getWindowData()->window);
}
return 0;
}
So after some more testing, the answer to my problem was that you have to wrap C header files in extern "C" before trying to include them into namespaces.
namespace LittleEngine {
namespace utils {
extern "C" {
# include "window.h"
}
# include "window.hpp"
}
}
However, even when doing this, it still puts the C-defines at the root namespace, which makes sense I guess.
Edit: Moreover, it does get a lot weirder than just that. In the above example, I can extern-C include the "window.h" file. The second I hop to another file and try to chain impl. this, I get the same error I started out with. TLDR; TIL only C++ includes go in namespaces.
Edit 2: I think it was just GLEW and SDL causing the issue. I hate programming. Why do I do this to myself?
Edit 3: After even more testing.. I think it was. So the biggest changes I made when refactoring is
Not including headers in sub-header files. You can do this because of how the Linker works.
I took out all the extern "C" because all that should theoretically do is disable C++ name wrangling, which doesn't make sense anyway.
I simply moved the SDL and GLEW includes out of scope of the namespace and suddenly it works.
Either way, my point still stands. Don't include C headers in C++ namespaces.
If somebody else wants to answer this in a preferably more detailed manner, I would be happy to mark that as the answer.

Failed to create GLFW window?

I tried to create a window with the simplest code possible:
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h> // Always include it before glfw.h
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
int main(void) {
glfwInit();
glfwWindowHint(GLFW_VERSION_MAJOR, 3); // OpenGL 3.3
glfwWindowHint(GLFW_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // Mac
GLFWwindow* window = glfwCreateWindow(720, 480, "OpenGL", NULL, NULL); // Create a window
if (window == NULL) {
fprintf(stderr, "Failed to create window\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
return 0;
}
This is my Makefile:
game:
g++ src/main.cpp -std=c++17 -o play -I include -L lib -l glfw.3 -l GLEW.2.2
When I compile my code there is no error, but when I try to play my code I have this error:
Failed to create window
Invalid window hint 0x00000003
Invalid window hint 0x00000003
Context profiles are only defined for OpenGL version 3.2 and above
Can someone help me? I don't know why my window doesn't want to be created...
GLFW_VERSION_MAJOR & GLFW_VERSION_MINOR are not valid arguments to glfwWindowHint:
glfwWindowHint(GLFW_VERSION_MAJOR, 3); // OpenGL 3.3
^^^^^^^^^^^^^^^^^^ nope
glfwWindowHint(GLFW_VERSION_MINOR, 3);
^^^^^^^^^^^^^^^^^^ also nope
Use GLFW_CONTEXT_VERSION_MAJOR & GLFW_CONTEXT_VERSION_MINOR instead.
As per the docs, emphasis mine:
GLFW_CONTEXT_VERSION_MAJOR and GLFW_CONTEXT_VERSION_MINOR specify the client API version that the created context must be compatible with. The exact behavior of these hints depend on the requested client API.
Note: Do not confuse these hints with GLFW_VERSION_MAJOR and GLFW_VERSION_MINOR, which provide the API version of the GLFW header.

I am struggling to set up OpenGL and GLAD

I am reading a book called learn OpenGL and I am struggling with the set up. I am using code blocks. What I have done so far is:
I downloaded the 32 bit binaries for GLFW from this website: http://www.glfw.org/download.html
I also downloaded GLAD from this website:
http://glad.dav1d.de/
I then added all the files from these downloads to an include folder. After this I added glad.c and glad.h to my project. Then in codeblocks I clicked the project tab then went to build options - search directories - compiler and added the 2 include folders that I got from the downloads and the src folder. Then in search directories I went to linker and added lib-mingw.
The book I am reading told me to add this code:
#include <GLFW/glfw3.h>
#include <iostream>
int main()
{
//setting the version of openGL
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//creating a window
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window = NULL)
{
std::cout <<"Failed to create GLFW window\n";
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, 800, 600);
return 0;
}
My problem is I keep getting the error: 'GLADloadproc' was not declared in this scope and 'GLADLoadGLLoader' was not declared in this scope. Also I have tried putting the glad folder into my project file directory so that the #include <glad/glad.h> can be found. What could be the problem?

how to use GLFW with openGL?

I'm trying to compile a short openGl and GLFW code but I'm failing in..
I've included all the .h like this :
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glfw2.h>
I'm on linux so I've made a :
sudo zypper install libglfw2
When I'm compiling like this :
g++ main.cpp -lGLU
I have :
main.cpp:14:22: fatal error: GL/glfw2.h:Any file or directory
#include <GL/glfw2.h>
^
compilation terminated.
I've also tried to include #include <GL/glfw3.h> but without success.
This is my complet code :
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glfw2.h>
int main()
{
if (glfwInit() == false)
{
fprintf(stderr, "GLFW failed to initialise.\n");
return (-1);
}
glfwWindowHint(GLFW_FSAA_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window;
window = glfwCreateWindow(640, 480, "OPENGL", NULL, NULL);
if (!window)
{
fprintf(stderr, "Window failed to create\n");
glfwTerminate();
return (-1);
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
return (-1);
}
return (0);
}
Could someone know what I have to do to compile my code ?
Thanks
There is no GL/glfw2.h and never has been, and the code above uses the GLFW 3 API. See Renamed library and header file for more information about header paths.
There is no reason to use GLFW 2 for new projects, so I would avoid the libglfw2 package. Instead see if there is a GLFW 3 package.

c++, Identifier is undefined when part of the code is put in another cpp file

i'm sorry if the question layout is weird or something this is my first time asking a question. I have started learning c++ a week ago and now that i know how to create a window with GLFW I would like to clean up my code and make it nicer. I tried to put the "create window" stuff inside a .cpp file named "window.cpp" and then import it to the main file. but when i take out the GLFWCreateWindow function it doesn't recognize the window name "w_gill" in the swapbuffer, windowshouldclose and destroywindow functions. Can anyone please help me?
Here is the Main.cpp file:
#include <iostream>
#include <Windows.h>
#include "window.cpp"
int main(){
do{
createWindow();
glfwSwapBuffers(w_gill);
glfwPollEvents();
} while (!glfwWindowShouldClose(w_gill));
glfwDestroyWindow(w_gill);
glfwTerminate();
return 0;
}
And the Window.cpp file:
#include <GL\glew.h>
#include <GLFW\glfw3.h>
int windowWidth = 1920 / 2;
int windowHeight = 1080 / 2;
int createWindow(){
if (!glfwInit())
{
glfwTerminate();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_VERSION_MINOR, 4);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
GLFWwindow* w_gill;
w_gill = glfwCreateWindow(windowWidth, windowHeight, "Gillow", NULL, NULL);
if (!w_gill)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(w_gill);
glfwSetInputMode(w_gill, GLFW_STICKY_KEYS, GL_TRUE);
}
Nevermind I got it, I had to put
GLFWwindow* w_gill;
int createWindow();
inside of the main.cpp file so they are linked. Thanks for responding anyway.
Your problem has to do with the "scope" or lifetime that a variable has in C. The scope of w_gill is local to its containing function, and as such, there is no visibility to that variable outside of the function. In addition to moving the createWindow() function to its own .CPP file, you must have made some other changes, as even if it was still in main.cpp you would still have the same issue.