SDL2 library fails to initialize - c++

I'm currently working with SDL2 and GLFW3 to create some OpenGL game. Initializing and using GLFW3 is no problem; I'm using GLFW3 for creating the OpenGL context, window, key input etc. and SDL2 for loading images to SDLSurfaces and then converting them to OpenGL textures, but, unlike GLFW3, SDL2 fails to initialize. My initialization code looks like this:
if (!SDL_Init(SDL_INIT_EVERYTHING)) return -1;
It always returns -1 and quits the main function. Does anyone know why this could happen?

The problem
The problem is not with SDL. SDL actually initializes completely fine. The problem is how you check if the initialization succeeded. Take a look at the documentation for SDL_Init()
Returns 0 on success or a negative error code on failure; call
SDL_GetError() for more information.
In your code code
if (!SDL_Init(SDL_INIT_EVERYTHING)) return -1;
In the if, the SDL_Init(SDL_INIT_EVERYTHING) part will return 0, which evaluates to false but it still means that SDL was successfully initialized. The ! in front, means the entire if will evaluate to true, and -1 will be returned.
Solution
A better soltion is to check if it's equal to 0 and if it does fail, used SDL_GetError() to print the error.
if ( SDL_Init(SDL_INIT_EVERYTHING) != 0 )
{
std::cout << "Error : " << SDL_GetError() << std::endl;
return -1;
}

Related

Why would fstream.fail() return true or false

I'm working through some work with some code already provided. There is an if statement that includes 2 fstream.fails(). The code is continually returning true and I'm not sure if it's because of a problem with the provided code or if I am missing something.
I've googled around to try and better understand what could be going on, but due to me being new to C++, I'm finding it hard to find an answer that helps me understand what might be going on.
The provided code where I think might be a problem.
bool Navigation::BuildNetwork(const string &fileNamePlaces, const string &fileNameLinks)
{
fstream finPlaces(fileNamePlaces);
fstream finLinks(fileNameLinks);
if (finPlaces.fail() || finLinks.fail()) return false;
ifstream();
// Add your code here
}
Where the "Build network" function is called
ACW_Wrapper wrapper("log.txt");
// Build Navigation
wrapper.startTimer();
Navigation nav;
if (nav.BuildNetwork("Places.csv", "Links.csv")) {
const auto elapsed = wrapper.stopTimer();
std::cout << std::fixed << std::setprecision(1) << "BuildNetwork - " << elapsed << " microseconds" << std::endl;
}
else {
std::cout << "\n*** Error *** BuildNetwork" << std::endl;
}
I would expect it to return false since this is provided code, but I'm unsure if I need to add something that would give me the expected outcome.
From the ios::fail documentation:
true if badbit (Read/writing error on I/O operation) and/or failbit (Logical error on i/o operation) are set.
which suggests that at least one of the two files is not opened successfully.
The problem is not in the code, the problem is with your program trying to open files that are not probably found (or it doesn't have permissions to).
Copy the files to the same workspace (folder) with your executable, and try again.

glewInit and building dll

I am developing hobby opengl3 engine and I decided to make a new .dll build of it. It uses GLEW to get opengl3 functions from GPU. I've successfully builded it about 5 months ago, but now I've changed a lot and it doesn't want to get working.
So the .dll builds perfectly (windows7, mingw).
I've made a simple program and it crashes on first call to glCreateProgram which is runned by code from mylib.dll.
in pseudocode:
#include "mylib.hpp"
int main(){
std::cout << (void*)glCreateProgram << "\n";
// displays 0 as glCreateProgram haven't been loaded yet
myspace::Window* = new SDL2BasedWindow(...);
//this constructor is from my .dll and calls glewInit() which returns GLEW_OK
std::cout << (void*)glCreateProgram << "\n";
//this displays proper address
int testGLEW= glCreateProgram();
std::cout << "glCreateProgram from main: " << testGLEW<< "\n";
//this displays 1 which means valid call to glCreateProgram
window->runApplication(new Application(...));
//Application is user-defined class, it further creates myspace::ShaderProgram
//which is imported from my .dll (part of my engine) which then calls
//glCreateProgram in it's initialisation
//(it is first call to any function which should be initialized by GLEW if we count only code imported from mylib.dll)
}
//in ShaderProgram constructor:
std::cout << "trying to call glCreateProgram, address: ";
std::cout << (void*)glCreateProgram << "\n"; //this displays 0 (!)
int id = glCreateProgram(); //this ends execution with SIGSEGV
printf("created program: %d\n", id); //so this one is never called
So my question is, why GLEW works only in code which is not imported from my .dll and how can I fix it?
Btw I've checked nm mylib.dll ant it contains glCreateProgram and other glew dependent functions, I also use #define GLEW_STATIC both in .dll and program that uses this .dll
Thanks for your help!
#define GLEW_STATIC is used to build a static library or executable.
To build a .dll use #define GLEW_BUILD instead.

Allegro 5: trouble storing bitmaps in a std map

I started creating a game in Visual Studio 2017 in C++ using Allegro 5. In order to make it easier to manage images, I created an ImageLoader class which would load and store all active images, and destroy them as necessary. It does so using a map which matches filenames to the corresponding images.
Currently my main() code looks like this:
int main(){
if (!al_init()) {
al_show_native_message_box(NULL, NULL, NULL, "Could not intialize allegro 5.", NULL, NULL);
return -1;
}
ALLEGRO_DISPLAY *display = al_create_display(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT);
al_set_window_title(display, "Game title");
// make usre the display was created correctly
if (!display) {
al_show_native_message_box(display, "Title", "settings", "Could not create Allegro window.", NULL, NULL);
}
// intialize fonts, primitives, keyboard,etc.
al_init_font_addon();
al_init_ttf_addon();
al_init_primitives_addon();
al_install_keyboard();
if(!al_init_image_addon()) {
al_show_native_message_box(display, "Error", "Error", "Failed to initialize al_init_image_addon!",
NULL, ALLEGRO_MESSAGEBOX_ERROR);
return -1;}
ImageLoader image_loader;
The ImageLoader then loads an image for the player:
ALLEGRO_BITMAP *image = al_load_bitmap(filename);
if (image == NULL) {
std::cout << filename << std::endl;
std::cout << "loader failed to load image" << std::endl;
}
image_map[filename] = image;
When I test this part, it seems to work, as the image is not null. Note that image_map is declared like so in ImageLoader.h:
std::map<const char *, ALLEGRO_BITMAP*> image_map;
The problem arises in my main game loop when I then try to get the image from the ImageLoader:
for (GameImage image : imageList) {
ALLEGRO_BITMAP *draw_image = image_loader.get_current_image(image);
if (draw_image == NULL) {
//TODO: error handling
std::cout << "no image" << std::endl;
}
else
al_draw_bitmap(draw_image, image.get_x(), image.get_y(), NULL);
}
My check always shows that draw_image is null. Here is the code for get_current_image:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
return image_map[image.get_image_filename()];
}
I have tested to make sure I'm using the same filename here as when I load the image and store it in the map by checking if (image_map.find(image.get_image_filename()) == image_map.end()), but even though this returns false the ALLEGRO_BITMAP pointer is still null. I have tried making the map store bitmaps instead of pointers, but this gives me an error when I try to add an element to the map since I'm not allowed to modify map values like this. Why might these pointers become null in between the time where I set them and the time where I retrieve them? I'm also open to other suggestions for how I should store my bitmaps.
EDIT: I revised my project, changing the instances of filenames as char arrays to std::strings. The image map is now declared as std::map<std::string, ALLEGRO_BITMAP*> image_map in ImageLoader.h, and the filename stored by GameImage is now std::string image_filename. load_image in ImageLoader.cpp now looks like this:
ALLEGRO_BITMAP *image = al_load_bitmap(filename.c_str());
if (image == NULL) {
std::cout << filename << std::endl;
std::cout << "loader failed to load image" << std::endl;
}
image_map[filename] = image;
Finally, get_current_image is still the same:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
return image_map[image.get_image_filename()];
}
However, the same problem still persists. I have also checked the size of the image map and it stays at 1 throughout the duration of my program, with the filename for the image I insert as the key and the value starting as a non-null pointer to an bitmap and appearing to become null at some point.
EDIT 2:
After changing the char arrays to strings and fixing get_current_image() so that it no longer adds to the map if the searched filename is not found, I discovered that I had also made a mistake when loading the images in a line I'd forgotten to include when I initially posted the question:
current_screen.load_images(image_loader);
As it turned out, I had written load_images() like so:
void MainGameScreen::load_images(ImageLoader loader)
...meaning that the calls the function made to loader weren't actually applying to the ImageLoader I'd passed in. I changed it to:
void MainGameScreen::load_images(ImageLoader& loader)
...and now everything works fine.
Your problem is that using const char * as your key means that map is going to perform a direct address comparison, i.e. "Is the address of the string equal to the address of the string I'm holding in memory". This is almost certainly NOT the way you want to perform string comparisons.
There's actually two solutions to this problem, depending on your use-case. The first is to simply change const char * to std::string, which is the simplest solution and what you should have done by default.
std::map<std::string, ALLEGRO_BITMAP*> image_map;
And, broadly speaking, anywhere that you are using a string, you should either be using std::string or std::string const&. There's no reason to use anything else.
...UNLESS you're concerned about performance. And if you're writing a game, performance is almost certainly something you care about, which brings us to the second solution. Having to do lots of lookups to a map is going to invoke a large number of comparisons, and while this isn't normally a huge issue, it is here because each comparison is a full-blown string-based equality check.
The solution is, when you load images, issue each image a unique ID (like an int64_t or uint64_t), and assign those values to the GameImage object instead of the filename or pathname. Then, when you do lookups, use that ID to perform the lookup.
It's up to you. Swapping out const char * with std::string is almost certainly going to fix the logical errors in your code and make it work the way you expect. The rest is more of an optimization problem if you discover that having to do all those string comparisons is slowing down your program too dramatically.
EDIT:
Your new problem is that std::map's operator[] function automatically inserts a default value (in this case, nullptr) if it fails to find any pre-existing image with the name requested. The code you want looks more like this:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
auto it = image_map.find(image.get_image_filename());
if(it == image_map.end()) return nullptr;
else return it->second;
//return image_map[image.get_image_filename()];
}
This way, failure to find an image won't trick any debugging tools you use into thinking that a valid (null) value is stored at that location.
You could also simplify it to this if you wanted to use the built-in exception facilities instead:
ALLEGRO_BITMAP * ImageLoader::get_current_image(GameImage image)
{
//Will throw an exception if nothing is found
return image_map.at(image.get_image_filename());
}

Very slow startup using SDL 2 on OS X 10.8

Even using the most basic SDL test, when I run the output file after compiling, I get a pinwheel for about 8 seconds, and then the program starts.
This doesn't happen if I don't use SDL.
I have tried both clang and g++ with the same results.
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, char **argv){
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Quit();
return 0;
}
Is this normal, or is there a way to fix this? It's really annoying for quickly testing :(
I've found initializing the joysticks tends to take a long time across multiple platforms.
My solution is to initialize just the video to begin with, then later initialize other stuff separately.
SDL_Init(SDL_INIT_VIDEO);
// You can create your window and display a splash screen here
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
SDL_InitSubSystem(SDL_INIT_AUDIO);

GLEW functions can't be found

I am on Ubuntu, writing an application using OpenGL, GLEW and GLFW. I am using Eclipse as my IDE, and am having problems when trying to use functions such as glGenRenderbuffer. I have a very similar structure set up under Windows but can't get it to work on Linux.
I am linking to the libraries glfw and GLEW. I am able to compile and run parts of my application and can initialize both GLFW and GLEW. From these test runs I learn the following:
OpenGL version: 4.2.0 NVIDIA 304.64
Using GLEW 1.6.0
However, I can't get the function glGenRenderbuffer (or other framebuffer functions) to compile. I have tried adding both EXT and ARB to the name, as well as playing around with glex.h without any luck. As far as I know, the purpose of GLEW is to handle all extension issues, right?
The source file (VolumeRenderer.cpp) includes are done like this:
#include <glm/gtc/matrix_transform.hpp>
#include <VolumeRenderer.h>
#include <GL/glew.h>
#include <GL/glfw.h>
Further down, I am trying to use the function like this (only partially complete function, of course):
bool VolumeRenderer::InitFramebuffers()
{
glGenRenderbuffers(1, &renderBufferObject_);
return true;
}
All I get is "function 'glGenRenderBuffers' could not be resolved".
Looking in the GL/glew.h header I am including, I found the following lines among others:
#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers)
#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT)
But the compiler still can't find the function. Is there anything I have forgotten, or maybe some tests and checks I can run to see what is happening?
Alright, so I got it to work by basically copying my Eclipse project file by file into a new, empty project. However, I did some other things before that. First, I moved around the includes as suggested in the helpful comments. I also removed things like glm. No success! Then I made a simple project in Eclipse with one single .cpp file, and linked to glfw and GLEW:
#include <GL/glew.h>
#include <GL/glfw.h>
#include <iostream>
#include <cstdlib>
int main()
{
if (glfwInit() != GL_TRUE) {
std::cout << "glfwInit() failed\n";
exit(1);
}
if (!glfwOpenWindow(800, 600, 8 , 8, 8, 8, 8, 8, GLFW_WINDOW)) {
std::cout << "glfwOpenWindow() failed\n";
exit(1);
}
char *glVersion = (char*)glGetString(GL_VERSION);
if (glVersion) {
std::cout << "OpenGL version: " << glVersion << "\n";
}
GLenum err = glewInit();
if (err != GLEW_OK) {
std::cout << "GLEW init failed: " << glewGetErrorString(err) << "\n";
exit(1);
} else {
std::cout << "Using GLEW " << glewGetString(GLEW_VERSION) << "\n";
}
GLuint buf;
glGenRenderbuffers(1, &buf);
exit(0);
}
That worked like a charm. I then tried to recreate my old problem by making another project with a similar file and include structure, and it seemed to work fine too. I then started a third, empty project where I simply made exact copies of the files that were originally giving me trouble. Now I have an exact copy of the original project (that now had the include order changed) with the exact same libraries linked to it, and it works. I still don't know what happened but I suspect that my project in Eclipse got messed up somehow, and never recovered even though I made some changes.