I have the following code, the goal is to open an SDL window that displays a timer in milliseconds. So I use SDLttf, SDL2 and Getsystemtime() to get the timer. I get those linker errors :
Error 3 error LNK2019: unresolved external symbol _snprintf referenced in function _SDL_main ...\Source.obj PROJECT
Error 4 error LNK1120: 1 unresolved externals PROJECT.exe PROJECT
The code :
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_ttf.h>
#include <windows.h>
int main(int argc, char ** argv)
{
int quit = 0;
SDL_Event event;
char timertxt[1024];
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
SYSTEMTIME st1, st2;
GetSystemTime(&st1);
SDL_Window * window = SDL_CreateWindow("SDL_ttf in SDL2",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 200,150, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
TTF_Font * font = TTF_OpenFont("arial.ttf", 25);
const char * error = TTF_GetError();
SDL_Color color = { 255, 255, 255 };
SDL_Surface * surface;
SDL_Texture * texture;
int texW = 0, texH = 0;
SDL_Rect dstrect;
while (!quit)
{
SDL_PollEvent(&event);
SDL_Delay(1);
switch (event.type)
{
case SDL_QUIT:
quit = 1;
break;
}
GetSystemTime(&st2);
snprintf(timertxt, sizeof(timertxt), "%d", st1.wMilliseconds);
surface = TTF_RenderText_Solid(font, timertxt, color);
texture = SDL_CreateTextureFromSurface(renderer,surface);
SDL_QueryTexture(texture, NULL, NULL, &texW, &texH);
dstrect = (SDL_Rect){ 0, 0, texW, texH };
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
TTF_CloseFont(font);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return 0;
}
I don't see what is the problem using snprintf in the sme code as SDL.
Use _snprintf or _snprintf_s versions instead of snprintf. In Windows it is considered a deprecated POSIX function.
The following POSIX names for functions are deprecated. In most cases, prepending an underscore character gives the standard equivalent name.
Check this link:
http://msdn.microsoft.com/en-us/library/ms235384%28v=vs.90%29.aspx
Related
I'm trying to use C to create a webassembly program to write text to an HTML5 canvas. I'm getting a segfault.
I've been looking at this tutorial: https://lyceum-allotments.github.io/2016/06/emscripten-and-sdl2-tutorial-part-6-write-owl/
This is my main.c file:
#include <stdio.h>
#include <SDL2/SDL.h>
#include <emscripten.h>
#include <stdlib.h>
#include <math.h>
#include <SDL2/SDL_ttf.h>
/**
* A Context structure that can be used to pass variables into the loop
*/
//
struct Context {
SDL_Renderer *renderer;
int iteration;
// Rectangle that texture will be rendered into
TTF_Font *font;
SDL_Texture *text_texture;
} Context;
/**
* size of the canvas in pixels
*/
const int WINDOW_WIDTH = 1600;
const int WINDOW_HEIGHT = 420;
void set_font_text(struct Context *ctx, const char *text) {
SDL_Color fg = {0,0,0,255};
SDL_Surface *text_surface = TTF_RenderText_Blended(ctx->font, text, fg);
ctx->text_texture = SDL_CreateTextureFromSurface(ctx->renderer, text_surface);
SDL_FreeSurface(text_surface);
SDL_DestroyTexture(ctx->text_texture);
}
int get_font_texture(struct Context *ctx) {
ctx->font = TTF_OpenFont("assets/fonts/Alef-Regular.ttf", 30);
set_font_text(ctx, "NEIL DU TOIT");
TTF_CloseFont(ctx->font);
TTF_Quit();
return 1;
}
/**
* The loop handler, will be called repeatedly
*/
void mainLoop(void *arg) {
struct Context *ctx = arg;
// Set background color and clear canvas
SDL_SetRenderDrawColor(ctx->renderer, 100, 143, 154, 255);
SDL_RenderClear(ctx->renderer);
SDL_Rect text_dest = {.x = 50, .y = 175, .w = 0, .h = 0};
SDL_QueryTexture(ctx->text_texture, NULL, NULL, &text_dest.w, &text_dest.h);
SDL_RenderCopy(ctx->renderer, ctx->text_texture, NULL, &text_dest);
SDL_RenderPresent(ctx->renderer);
}
int main() {
SDL_Window *window;
struct Context ctx;
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &ctx.renderer);
SDL_SetRenderDrawColor(ctx.renderer, 255, 143, 154, 255);
get_font_texture(&ctx);
ctx.iteration = 0;
int infinite_loop = 1;
int fps = -1;
emscripten_set_main_loop_arg(mainLoop, &ctx, fps, infinite_loop);
SDL_DestroyRenderer(ctx.renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
Comiled using:
emcc main.c -s USE_SDL=2 -s WASM=1 -s USE_SDL_TTF=2 -O3 -o main.js
and served with:
python3 -m http.server 8000
When opened I immediately see:
If I remove the call to set_font_text the error goes away (but I don't see any text of course)
What's going wrong?
So I've recently started to learn SDL2, and I am trying run a simple program, but I don't know what I'm doing wrong. My IDE (Code Blocks) says that the line of code SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); has some kind of error and won't run. What am I missing or doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
static const int width = 800;
static const int height = 600;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); // <-Supposed Error
SDL_Window *window = SDL_CreateWindow("Hey\n", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRendererDrawColor(renderer, 255, 0, 0, 255);
bool running = true;
SDL_Event event;
while(running)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
The linker error that I get is:
undefined reference to `SDL_SetRendererDrawColor'
Because this function doesn't exist in SDL2, you must use SDL_SetRenderDrawColor().
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
I'm using the SDL2 library, in C.
I made a test program to open a white window, but I get a segmentation fault with the function SDL_FillRect even though there are no errors or warnings when I build it.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
static const int window_width = 1000;
static const int window_height = 1000;
int main(int argc, char* argv[])
{
//Window
SDL_Window *window = NULL;
//Window Surface where things will be shown
SDL_Surface *surface = NULL;
//Inicializar SDL
if(SDL_Init(SDL_INIT_VIDEO) == -1)
{
printf("Failed to initialize SDL2. SDL Error: %s", SDL_GetError());
}
else
{
window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_SHOWN );
if(window == NULL)
printf("Failed to create SDL2 window. SDL Error: %s", SDL_GetError());
else
{
//Fill window with white color
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0xFF, 0xFF, 0xFF));
//Update surface with new changes
SDL_UpdateWindowSurface(window);
//Wait before closing (parameter in miliseconds)
SDL_Delay(4000);
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
You get Segmentation fault because surface is still NULL
This example code taken directly from the SDL wiki (https://wiki.libsdl.org/SDL_FillRect) shows how to create a SDL_Surface before calling SDL_FillRect()
/* Declaring the surface. */
SDL_Surface *s;
/* Creating the surface. */
s = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
/* Filling the surface with red color. */
SDL_FillRect(s, NULL, SDL_MapRGB(s->format, 255, 0, 0));
This SDL program works fine (displays a windows and a draws a bitmap onto it), however, if I declare any variables in my program (such as int, long, etc), the windows freezes and is white instead of black and nothing draws. What could possibly cause this?
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
int main(int argc, char* argv[]) {
// line below will cause SDL crash
// int blabla = 640;
SDL_Window *window;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(
"A rather exceptional SDL window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_OPENGL
);
if (window == NULL) {
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
SDL_Renderer *renderer;
SDL_Texture *texture;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface *brush;
brush = IMG_Load("brush2.png");
texture = SDL_CreateTextureFromSurface(renderer, brush);
SDL_RenderClear(renderer);
SDL_Rect *sRect, *dRect;
sRect->w = 10;
sRect->h = 4;
sRect->x = 0;
sRect->y = 0;
dRect->w = 10;
dRect->h = 4;
dRect->x = 10;
dRect->y = 10;
SDL_RenderCopy(renderer, texture, sRect, dRect);
SDL_RenderPresent(renderer);
SDL_Delay(1000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
You are writing unallocated memory.
SDL_Rect *sRect, *dRect;
sRect->w = 10; /* w doesn't exist. Writing is undefined behaviour. */
sRect and dRect are only pointers. They need to point to valid memory before struct members are accessed.
You could declare them in stack instead:
SDL_Rect sRect, dRect;
sRect.w = 10;
sRect.h = 4;
...
SDL_RenderCopy(renderer, texture, &sRect, &dRect);
You should also check return values of SDL_-functions. If those fail, and you continue execution regardless, you may experience weird behaviour or crashes.
In SDL2 I want to be able to draw changes to one buffer rather than redraw the whole image to two different buffers as my setup seems to be doing. Below is a really quick test which shows the unwanted behavior:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>
// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
void putPixel(SDL_Renderer *renderer, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderDrawPoint(renderer, x, y);
}
int main(int argc, char* argv[]) {
int width = 640;
int height = 480;
SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
if (window == NULL)
{
return -1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
return -2;
}
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for(int x=0;x<8;x++)
{
for(int y=0;y<10;y++)
{
putPixel(renderer,40+x*10,50+y);
}
SDL_RenderPresent(renderer);
sleep(1);
}
SDL_Quit();
return 0;
}
The output from this is two alternating screens. It is obviously using a double buffer which means I have to clear and redraw to get the output I want. After each cycle of the for...loop I wanted to add a line to the buffer - there should have been 8 lines at the end of the program running. In this case I got 4 on one buffer and 4 on another. I don't want to redraw the previous lines again either, hence the need for one buffer:
This uses a texture as a buffer and copies this to the screen when done.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>
// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
void putPixel(SDL_Renderer *renderer, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 255,255,255,255);
SDL_RenderDrawPoint(renderer, x, y);
}
int main(int argc, char* argv[]) {
int width = 640;
int height = 480;
SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
if (window == NULL)
{
return -1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
if (renderer == NULL)
{
return -2;
}
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
/* Create texture for display */
SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
SDL_SetRenderTarget(renderer, display);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for(int x=0;x<8;x++)
{
SDL_SetRenderTarget(renderer, display);
for(int y=0;y<10;y++)
{
putPixel(renderer,40+x*10,50+y);
}
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, display, NULL, NULL);
SDL_RenderPresent(renderer);
sleep(1);
}
SDL_Quit();
return 0;
}
The output from this is below: