3
votes

I just started a tutorial to learn C++ OpenGL using SDL. The steps shown in the videotutorial were done by using the IDE called Code Blocks, but I thought it was going to work also for Visual Studio 2012.

I downloaded the SDL2 developer which is for Windows x64 (my Windows 7 is 64 bits, but the Visual Studio 2012 I have is an x86 version)

To install the SDL2 in Visual Studio 2012, I put:

  • the .h files in the include folder (D:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\SDL).
  • the .lib files in the lib folder (D:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\lib\SDL).
  • the .dll file in C:/Windows/system folder.

After that, I opened the IDE, made a new project and while I was writting the code, autocompletion popped up for specific SDL features, meaning success... until I tried to run it.

This is the code I wrote according to the videotutorial:

#include "SDL.h"

int main(int argc, char* args[]){
    SDL_Init(SDL_INIT_EVERYTHING);

    SDL_Quit();

    return 0;
}

When I click on "Start Debugging" or "Start without debugging", after pressing yes to build it, the output comes with errors.

Here's a screenshot of the code I wrote, plus the output:

Screenshot of non-working opengl sdl in visual studio 2012

After that, I tried an older version of the SDL the tutorial was already using, which was the 1.2 (I overwrote few files of the newer version) but still no good results.

How do I fix it so I can practice with OpenGL + SDL features?

2
Don't post pictures where text would perfectly suffice.legends2k

2 Answers

5
votes

TLDR:

When you use a library in your project,

  • Compiling needs header filenames (#include <*.h>) and include directories containing them
  • Linking needs lib filenames (*.lib, what you're missing) and library directories containing them
  • Running needs dynamic libraries (*.dll), commonly using the same name as the .lib in the current or system directory (VS has binary directories too but I've never needed to know what they're for exactly)

When you compile code and add #include <SDL.h>, the compiler runs through a list of possible directories its been given to find that file. There are some default directories already set up, but so you don't have a mess of all your libraries in one place it's possible to add more. For example, Setting Global C++ Include Paths in Visual Studio 2012 (and 2011, and 2010). If your SDL.h is in a subdirectory in an include directory it won't be found - eg. just check this shouldn't be <SDL/SDL.h> or something similar.

With the include path set and the correct #include your code can compile. Now it's the linking stage. You've got some code that says I need the these functions and the linker has to either find the actual code for those functions and link them statically (all the code can be found in the .lib) or set up the program to link at runtime, dynamically (in which case the program needs to be able to find the .dll, and I think on windows you need a .lib file that goes with it).

So in addition to the include directory you need a library directory. Also, just like you said to the compiler #include <SDL.h> you need to tell the linker to look for the code for those functions defined in SDL.h in SDL.lib (which may end up actually providing the code at runtime when loading SDL.dll). I think specifying libraries could even be done through #pragma calls, but it's more common to see the library files specified as arguments to the linker program. As @ScottMcP-MVP said, append SDL.lib to the Project Properties->Configuration Properties->Linker->Input->Additional Dependencies list. If it still says unresolved external that generally means the linker still can't find the file, so check for typos and double check the directories. Worst case is a mismatch between SDL.h and SDL.lib or SDL.lib was compiled with different options or a different compiler.

The error you're receiving is the linker saying the compiler says I need an "external" function, SDL_Init, to make your code work but I haven't found/resolved-the-reference-to one in the list of libraries I've been given.

Just as an example/recap all these GUI options end up going to the compiler/linker. So for example a full compile line might look like this:

./compiler -I/path/to/my/includes -L/path/to/my/lib -lmylibrary.lib mycode.cpp  -o myexecutable.exe

Where mycode.cpp contains #include <mylibrary.h>. Note that here the ./compiler is operating as both compiler and linker. The process could be split into:

./compiler -I/path/to/my/includes mycode.cpp -o mycompiledcode.o
./linker -L/path/to/my/lib -lmylibrary.lib mycompiledcode.o -o myexecutable.exe

Once you have your executable it needs to be able to find SDL.dll when you run it. Exactly as you've done, the executable should search the windows system directory. It should also search its current directory. On linux you can set an rpath (not sure on windows). If you keep getting application configuration incorrect and the dll is definitely there it's time to grab dependency walker and see what dll name the program is actually trying to load. Worst case is the application finds a different version of the dll or something else with the same name before the desired one.

Good luck. OpenGL is great fun!!


[EDIT]

You can use either x32 or x64 lib files, but all your code must be the same. It'll probably be easier to start with x32, and if you need fast double computation and more ram then change. OpenGL doesn't have great support for x64 yet so it probably won't make much difference to you.

Additional Dependencies is where you put just "SDL.lib". This file then needs to exist in one of visual studio's library directories. If you don't get unresolved externals from SDL anymore then that part is fixed.

Your _main error is probably to do with a disgusting hack *spit* SDL uses. Straight after #include <SDL.h> put #undef main (may want to surround in #ifdefs in case it changes):

#include <SDL.h> //my include is <SDL2/SDL.h>, as I have both an SDL and SDL2 dir in my include path

#ifdef main
#undef main //remove SDL's main() hook if it exists
#endif

An important thing to note: generally use </> to include external libraries and "/" to include headers within your project - What is the difference between #include <filename> and #include "filename"?

1
votes

You have to link the lib file into your exe. See Project, Properties, Link, Additional Dependencies. Put the name of the lib file there.