PDA

View Full Version : I get a linker error when trying to compile example 1.1 from Red Book 8th edition



Starless
03-31-2016, 01:45 PM
I don't quite understand the extremely complicated process of compiling C++ code into machine binaries. I'm used to C# and Java that output to intermediate languages.

So far, I'm not liking this book. It doesn't explain anything very well.

On to my issue:

downloaded the source code.
created a new solution in VisualStudio 2015 as an empty C++ project.
created a .cpp file and pasted the code of example 1.1.
copied the whole include folder from the book's source to my solution
changed the #include <something.h> directives to #include "include/something.h" (because I copied the include folder to my solution, as explained above)


When I try to build, I get the following error: Error LNK1104 cannot open file 'glew_static_vs2010_d.lib'

I'll paste the code bellow:


#include <iostream>
#include "include/vgl.h"
#include "include/LoadShaders.h"

using namespace std;

enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };

GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;

// -------------------------------------------------------------------- -
//
// init
//
void init(void)
{
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertices[NumVertices][2] = {
{ -0.90, -0.90 }, // Triangle 1
{ 0.85, -0.90 },
{ -0.90, 0.85 },
{ 0.90, -0.85 }, // Triangle 2
{ 0.90, 0.90 },
{ -0.85, 0.90 }
};
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),
vertices, GL_STATIC_DRAW);
ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, "triangles.vert" },
{ GL_FRAGMENT_SHADER, "triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders(shaders);
glUseProgram(program);
glVertexAttribPointer(vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vPosition);
}
//---------------------------------------------------------------------
//
// display
//
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glFlush();
}

//---------------------------------------------------------------------
//
// main
//
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(512, 512);
glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow(argv[0]);
if (glewInit()) {
cerr << "Unable to initialize GLEW ... exiting" << endl;
exit(EXIT_FAILURE);
}
init();
glutDisplayFunc(display);
glutMainLoop();
}

now, the code for vgl.h:


#ifndef __VGL_H__
#define __VGL_H__

// #define USE_GL3W

#ifdef USE_GL3W

#include <GL3/gl3.h>
#include <GL3/gl3w.h>

#else

#define GLEW_STATIC

#include "GL/glew.h"

#ifdef _MSC_VER
# ifdef _DEBUG
# if (_MSC_VER >= 1600)
# pragma comment (lib, "glew_static_vs2010_d.lib")
# else
# pragma comment (lib, "glew_static_d.lib")
# endif
# else
# if (_MSC_VER >= 1600)
# pragma comment (lib, "glew_static_vs2010.lib")
# else
# pragma comment (lib, "glew_static.lib")
# endif
# endif
#endif

#endif

#define FREEGLUT_STATIC

#include "GL/freeglut.h"

#ifdef _MSC_VER
# ifdef _DEBUG
# if (_MSC_VER >= 1600)
# pragma comment (lib, "freeglut_static_vs2010_d.lib")
# else
# pragma comment (lib, "freeglut_static_d.lib")
# endif
# else
# if (_MSC_VER >= 1600)
# pragma comment (lib, "freeglut_static_vs2010.lib")
# else
# pragma comment (lib, "freeglut_static.lib")
# endif
# endif
#endif

#define BUFFER_OFFSET(x) ((const void*) (x))

#endif /* __VGL_H__ */

and finally the code for LoadShaders.h


//////////////////////////////////////////////////////////////////////////////
//
// --- LoadShaders.h ---
//
//////////////////////////////////////////////////////////////////////////////

#ifndef __LOAD_SHADERS_H__
#define __LOAD_SHADERS_H__

#include <GL/gl.h>

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

//----------------------------------------------------------------------------
//
// LoadShaders() takes an array of ShaderFile structures, each of which
// contains the type of the shader, and a pointer a C-style character
// string (i.e., a NULL-terminated array of characters) containing the
// entire shader source.
//
// The array of structures is terminated by a final Shader with the
// "type" field set to GL_NONE.
//
// LoadShaders() returns the shader program value (as returned by
// glCreateProgram()) on success, or zero on failure.
//

typedef struct {
GLenum type;
const char* filename;
GLuint shader;
} ShaderInfo;

GLuint LoadShaders( ShaderInfo* );

//----------------------------------------------------------------------------

#ifdef __cplusplus
};
#endif // __cplusplus

#endif // __LOAD_SHADERS_H__

I'm using Windows 10. OpenGL version is 4.5. _MSC_VER referenced in vgl.h is defined as 1900. What am I doing wrong?

UPDATE:

the code now compiles. I made some changes to it. I'll post it here or in pastebin if anyone thinks necessary. I'm getting an "Access Violation", which sounds like I'm trying to dereference something out of my application memory space, probably OS space. I don't know why is that here is a minimized version of the update (ask for more if you think it's needed):



#include <Windows.h>
#include <iostream>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include "load_shaders.h"

using namespace std;

const int vPosition = 0;

GLuint vertex_array_id;

void init(void)
{
cout << "begin_init" << endl;
GLuint vertex_names[] = { 0 };
cout << "vertex_names array properly initialized with 0" << endl;
cout << flush;
glGenVertexArrays((GLsizei)1, vertex_names);//all lines above output. So this must be the problematic one

/* ... other stuff that doesn't matter since the program crashes above */
}


I undestand glGenVertexArrays is part of the OpenGL standard, but glew.h makes quite a bit of esoteric things (at least to me) along its 17+ thousand lines. Making heavy use of preprocessor directives, probably in an attempt to make the source code as portable as possible.

So, when using glew.h, those OpenGL functions are not really functions but macros that after preprocessing should be expanded to the function call normally. and here is its definition:

#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays)

Now, GLEW_GET_FUN is another macro that basically just expands it's argument [#define GLEW_GET_FUN (x) x] unless both GLEW_MX and _WIN32 are defined. (No idea why).

Then there's __glewGenVertexArrays, which is an identifier of type PFNGLGENVERTEXARRAYSPROC (not kidding).

PFNGLGENVERTEXARRAYSPROC is actually a typedef: typedef void (PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
(GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); (which matches the signature of standard glGenVertexArrays)

Why then the moment I call glGenVertexArrays I get:

Exception thrown at 0x0000000000000000 in triangles.cpp.exe: 0xC0000005: Access violation executing location 0x0000000000000000.

SOLVED!
During the corrections I had to make so the code would compile I comited a typo. changed an f for a v (I have this problem outside of coding too, mixing up F's and V's, specially if I'm writing in my native language).

PS
I still don't like this book. C++ is already a nightmare as it is, having someone with poor teaching skills right a book on OpenGL was not a good idea.