GCC/SDL2 Hangs Indefinitely and Stops Responding - c

Hi guys Ive been at this issue for a few days now and cant find the answer. After a successful build of SDL2 my projects hang and dont respond. They dont accept input and hang indefinitely unless I close them using the command prompt window. Even the 'X' on the application window doesnt respond. As far as I can tell this issue seems to be related to the window itself as the program can draw to the renderer. Please help.
I am using Windows 7, MinGW32, Eclipse Europa and SDL2
See below for example of the problem....
Internal Builder is used for build
gcc -O0 -g3 -Wall -c -fmessage-length=0 -osrc\CTestProject.o ..\src\CTestProject.c
gcc -oCTestProject.exe src\CTestProject.o -lmingw32 -lSDL2main -lSDL2
Build complete for project CTestProject
Time consumed: 562 ms.
Here is the example program
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
int main(int argc, char* args[]) {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Event event;
SDL_Window* sdlWindow = SDL_CreateWindow("test",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,300,300,SDL_WINDOW_OPENGL);
SDL_Renderer* sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
while(event.type != SDL_QUIT){
SDL_RenderClear(sdlRenderer);
SDL_SetRenderDrawColor(sdlRenderer, 150, 0, 0, 255);
SDL_RenderPresent(sdlRenderer);
}
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow(sdlWindow);
SDL_Quit();
return EXIT_SUCCESS;
}

while(event.type != SDL_QUIT)
{
SDL_RenderClear(sdlRenderer);
SDL_SetRenderDrawColor(sdlRenderer, 150, 0, 0, 255);
SDL_RenderPresent(sdlRenderer);
}
You are comparing a variable that doesn't change in your while loop. You need to update it in every iteration of loop using SDL_PollEvent(&event) Something like this:
bool quit = false;
SDL_Event event;
// Loop while user hasn't quit
while ( !quit )
{
// Check all new event to see if a SDL_QUIT event has come in...
while (SDL_PollEvent(&event) )
{
// SDL_QUIT event has come in, quit.
if ( event.type == SDL_QUIT )
{
quit = true;
}
}
SDL_RenderClear(sdlRenderer);
SDL_SetRenderDrawColor(sdlRenderer, 150, 0, 0, 255);
SDL_RenderPresent(sdlRenderer);
}
Also I don't think you need SDL2_main anymore. At least I don't use it in my code.
Nor do you need #include <stdio.h> and #include <stdlib.h> in your specific example.
Tutorials
SDL2 is fairly new, so there aren't that much tutorials around. The only ones I know is TwinklebearDev.But in most cases SDL1.3 and SDL2 are quite similar. So in most cases you can use SDL1.3 code with SDL_Texture, SDL_Renderer and SDL_Window.You can have a look here for more information on porting from 1.3 to 2.0. For SDL1.3 I have used LazyFoo's tutorials.

Related

SDL_GetError() returning an undocumented error on macOS

So I am developing a set of wrapping utilities for SDL2 but have come across a strange issue. Whenever I poll for errors using SDL_GetError at the end of a frame, if I am touching the trackpad I get the following strange error message: Unknown touch device id -1, cannot reset. This error in quotes only shows one result on google and it seems to be an issue with macOS though with only one occurrence it's hard to be sure.
Here's a minimum reproducible example:
#include <SDL2/SDL.h>
#include <stdio.h>
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 100, 100, SDL_WINDOW_SHOWN);
while(1) {
SDL_Event e;
while(SDL_PollEvent(&e))
switch(e.type) {
case SDL_QUIT: {
SDL_DestroyWindow(window);
SDL_Quit();
exit(0);
break;
}
}
const char* err = SDL_GetError();
if(err[0]) {
printf("%s", err);
exit(-1);
}
}
}
I understand that this is a strange issue(and a potentially unanswerable one) so I really appreciate any answers or suggestions.
I am using a MacBook Pro 13-inch Mid 2012 running macOS Catalina(10.15.6). Compiled using clang 12.0.0
EDIT: I have downloaded the SDL2 source code to look for the error and the root cause seems to be this function:
static int
SDL_GetTouchIndex(SDL_TouchID id)
{
int index;
SDL_Touch *touch;
for (index = 0; index < SDL_num_touch; ++index) {
touch = SDL_touchDevices[index];
if (touch->id == id) {
return index;
}
}
return -1;
}
I am in the process of looking for why exactly this error is triggered and will update this post for any future people who encounter this error as well as filing a bug report to the SDL dev team

OpenCV fails to recognize webcam, but mplayer succeeds

As a first step on a larger project I was trying to display the imagem from my webcam using OpenCV:
#include <stdlib.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int
main()
{
cv::VideoCapture cap(-1);
if (!cap.isOpened())
exit(EXIT_FAILURE);
cv::Mat frame;
bool done = false;
while (!done) {
cap >> frame;
cv::imshow("webcam", frame);
done = (cv::waitKey(30) >= 0);
}
return EXIT_SUCCESS;
}
This returns an error code (!cap.isOpened() passes ,confirmed with gdb). Initially I had 0 instead of -1. When searching this site -1 was suggested, but it was to no avail. I also tried 1 through 3, as another user suggested it.
I can display my webcam using mplayer, more specifically mplayer tv:// -tv driver=v4l2.
v4l2 is the "video for linux" driver. I noticed OpenCV can be installed with such driver by compiling it with -DWITH_V4L and -DWITH_LIBV4L (v4l USE flag in Gentoo). After recompiling OpenCV with it, it successfully recognized the webcam. GTK support seems to be needed to display the image.

Creating window application in pure c on mac osx

I'm creating an application in pure C on Mac OSX.
What I want is to create window in witch my app will be stored.
Preferably I want it to be pure C solution, but if I have to use objective-c class to init window and then send context to my C code then it will be fine.
I'm not using xcode, only simple text editor in with I tried to import cocoa but it just generated a lot of errors.
So in summary my question is:
How in simple pure C generate code that will display osx window?
I did a translation of the accepted answer to Pure C:
// based on https://stackoverflow.com/a/30269562
// Minimal Pure C code to create a window in Cocoa
// $ clang minimal.c -framework Cocoa -o minimal.app
#include <objc/runtime.h>
#include <objc/message.h>
#include <Carbon/Carbon.h>
#define cls objc_getClass
#define sel sel_getUid
#define msg ((id (*)(id, SEL, ...))objc_msgSend)
#define cls_msg ((id (*)(Class, SEL, ...))objc_msgSend)
// poor man's bindings!
typedef enum NSApplicationActivationPolicy {
NSApplicationActivationPolicyRegular = 0,
NSApplicationActivationPolicyAccessory = 1,
NSApplicationActivationPolicyERROR = 2,
} NSApplicationActivationPolicy;
typedef enum NSWindowStyleMask {
NSWindowStyleMaskBorderless = 0,
NSWindowStyleMaskTitled = 1 << 0,
NSWindowStyleMaskClosable = 1 << 1,
NSWindowStyleMaskMiniaturizable = 1 << 2,
NSWindowStyleMaskResizable = 1 << 3,
} NSWindowStyleMask;
typedef enum NSBackingStoreType {
NSBackingStoreBuffered = 2,
} NSBackingStoreType;
int main(int argc, char *argv[])
{
// id app = [NSApplication sharedApplication];
id app = cls_msg(cls("NSApplication"), sel("sharedApplication"));
// [app setActivationPolicy:NSApplicationActivationPolicyRegular];
msg(app, sel("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
struct CGRect frameRect = {0, 0, 600, 500};
// id window = [[NSWindow alloc] initWithContentRect:frameRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO];
id window = msg(cls_msg(cls("NSWindow"), sel("alloc")),
sel("initWithContentRect:styleMask:backing:defer:"),
frameRect,
NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable,
NSBackingStoreBuffered,
false);
msg(window, sel("setTitle:"), cls_msg(cls("NSString"), sel("stringWithUTF8String:"), "Pure C App"));
// [window makeKeyAndOrderFront:nil];
msg(window, sel("makeKeyAndOrderFront:"), nil);
// [app activateIgnoringOtherApps:YES];
msg(app, sel("activateIgnoringOtherApps:"), true);
msg(app, sel("run"));
}
You can use Objective-C runtime API example (iOS) Creating an iOS app in pure C
Alternative the same code in obj-c :
echo '#import <Cocoa/Cocoa.h>
int main ()
{
#autoreleasepool{
[NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
id applicationName = [[NSProcessInfo processInfo] processName];
id window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 120, 120)
styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO];
[window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
[window setTitle: applicationName];
[window makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
[NSApp run];
}
return 0;
}' | gcc -fobjc-arc -framework Cocoa -x objective-c -o MicroApp - ; ./MicroApp
This will run Cocoa app with 1 window. Like on screenshot below
You can actually add menu using NSMenu
id applicationMenuBar = [NSMenu new];
id appMenuItem = [NSMenuItem new];
[applicationMenuBar addItem:appMenuItem];
[NSApp setMainMenu: applicationMenuBar];
Can you do this? Yes and no (you can do anything if you're persistent enough). Yes you can, but no you shouldn't. Regardless, this can be done for the incredibly persistent among you. Since coding up an example will take awhile, I found a generous soul on the net who already did it. Look at this repository on GitHub for the full code and explanations. Here are some snippets:
cmacs_simple_msgSend((id)objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
if (NSApp == NULL) {
fprintf(stderr,"Failed to initialized NSApplication... terminating...\n");
return;
}
id appDelObj = cmacs_simple_msgSend((id)objc_getClass("AppDelegate"), sel_getUid("alloc"));
appDelObj = cmacs_simple_msgSend(appDelObj, sel_getUid("init"));
cmacs_void_msgSend1(NSApp, sel_getUid("setDelegate:"), appDelObj);
cmacs_void_msgSend(NSApp, sel_getUid("run"));
As you'll notice, this code uses the Objective-C runtime API to create a faux AppDelegate. And creating the window is an involved process:
self->window = cmacs_simple_msgSend((id)objc_getClass("NSWindow"), sel_getUid("alloc"));
/// Create an instance of the window.
self->window = cmacs_window_init_msgSend(self->window, sel_getUid("initWithContentRect:styleMask:backing:defer:"), (CMRect){0,0,1024,460}, (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask), 0, false);
/// Create an instance of our view class.
///
/// Relies on the view having declared a constructor that allocates a class pair for it.
id view = cmacs_rect_msgSend1(cmacs_simple_msgSend((id)objc_getClass("View"), sel_getUid("alloc")), sel_getUid("initWithFrame:"), (CMRect){ 0, 0, 320, 480 });
// here we simply add the view to the window.
cmacs_void_msgSend1(self->window, sel_getUid("setContentView:"), view);
cmacs_simple_msgSend(self->window, sel_getUid("becomeFirstResponder"));
// Shows our window in the bottom-left hand corner of the screen.
cmacs_void_msgSend1(self->window, sel_getUid("makeKeyAndOrderFront:"), self);
return YES;
So, yes. You can write a Cocoa app in pure C. But I wouldn't recommend it. 90% of that code can be replaced by an xib file, and doing it this way really restricts your app because more advanced features of the Apple development stack really on Objective-C features. While it's technically possible to do everything this way, you're making it much harder than it ought to be.
I remember seeing this question about a year ago, back when I so desperately wished I could open up a d*** window, googling for days and only finding the type of answers you see above this post.
I was reading up on the operating system the Mac is built on - Berkley Software Distribution. http://codex.cs.yale.edu/avi/os-book/OS9/appendices-dir/a.pdf Where on page 17 the phrase "...X Windowing System developed at MIT" hit me and I remembered how I couldn't open up a window and how pissed I was about that, and I thought maybe this was finally the solution!
I googled "BSD X Window Programming" and stumbled my way into finally getting a window open in pure C.
I just discovered it so I'm not a master yet but look at this link https://en.wikibooks.org/wiki/X_Window_Programming/Xlib and go to the example, make sure to follow the comments at the top for how to compile with the X11 library (you can ignore the -Wall and -O commands as long as you have the -lX11).
If you can't compile, if it can't find the header files, you'll need to help it find the header files.
There might be a couple different places that the X11 includes could be on your system. More than likely you'll find it in /opt/X11/include which will have all the definitions of the headers you'll need.
You could include the full path in your C programs such as:
#include "/opt/X11/include/X11/Xlib.h"
But we want it to look like this #include <X11/Xlib.h>
So you could add this switch to GCC when you compile -I /opt/X11/include
Or go to your .profile or .bashrc or .bash_profile in your home directory and add:
export C_INCLUDE_PATH="$C_INCLUDE_PATH:/opt/X11/include"
/*
Simple Xlib application drawing a box in a window.
*/
From the wiki:
#include<X11/Xlib.h>
#include<stdio.h>
#include<stdlib.h> // prevents error for exit on line 18 when compiling with gcc
int main() {
Display *d;
int s;
Window w;
XEvent e;
/* open connection with the server */
d=XOpenDisplay(NULL);
if(d==NULL) {
printf("Cannot open display\n");
exit(1);
}
s=DefaultScreen(d);
/* create window */
w=XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
BlackPixel(d, s), WhitePixel(d, s));
// Process Window Close Event through event handler so XNextEvent does Not fail
Atom delWindow = XInternAtom( d, "WM_DELETE_WINDOW", 0 );
XSetWMProtocols(d , w, &delWindow, 1);
/* select kind of events we are interested in */
XSelectInput(d, w, ExposureMask | KeyPressMask);
/* map (show) the window */
XMapWindow(d, w);
/* event loop */
while(1) {
XNextEvent(d, &e);
/* draw or redraw the window */
if(e.type==Expose) {
XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
}
/* exit on key press */
if(e.type==KeyPress)
break;
// Handle Windows Close Event
if(e.type==ClientMessage)
break;
}
/* destroy our window */
XDestroyWindow(d, w);
/* close connection to server */
XCloseDisplay(d);
return 0;
}
Compile:
gcc -O2 -Wall -o test test.c -L /usr/X11R6/lib -lX11 -lm
Unfortunately the top rated answer doesn't work on new Apple Silicon powered machines due to an ABI mismatch. Basically on ARM64 you can't use the objc_msgSend declaration with variable arguments, you must specify the correct argument types for each call. Here is the version that runs on Apple Silicon:
// based on https://stackoverflow.com/a/59596600/834108
// Minimal Pure C code to create a window in Cocoa
// Adapted to work on ARM64
// $ clang minimal.c -framework Cocoa -o minimal.app
#include <objc/runtime.h>
#include <objc/message.h>
#include <Carbon/Carbon.h>
#define cls objc_getClass
#define sel sel_getUid
#define msg ((id (*)(id, SEL))objc_msgSend)
#define msg_int ((id (*)(id, SEL, int))objc_msgSend)
#define msg_id ((id (*)(id, SEL, id))objc_msgSend)
#define msg_ptr ((id (*)(id, SEL, void*))objc_msgSend)
#define msg_cls ((id (*)(Class, SEL))objc_msgSend)
#define msg_cls_chr ((id (*)(Class, SEL, char*))objc_msgSend)
// poor man's bindings!
typedef enum NSApplicationActivationPolicy {
NSApplicationActivationPolicyRegular = 0,
NSApplicationActivationPolicyAccessory = 1,
NSApplicationActivationPolicyERROR = 2,
} NSApplicationActivationPolicy;
typedef enum NSWindowStyleMask {
NSWindowStyleMaskBorderless = 0,
NSWindowStyleMaskTitled = 1 << 0,
NSWindowStyleMaskClosable = 1 << 1,
NSWindowStyleMaskMiniaturizable = 1 << 2,
NSWindowStyleMaskResizable = 1 << 3,
} NSWindowStyleMask;
typedef enum NSBackingStoreType {
NSBackingStoreBuffered = 2,
} NSBackingStoreType;
int main(int argc, char *argv[])
{
// id app = [NSApplication sharedApplication];
id app = msg_cls(cls("NSApplication"), sel("sharedApplication"));
// [app setActivationPolicy:NSApplicationActivationPolicyRegular];
msg_int(app, sel("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
struct CGRect frameRect = {0, 0, 600, 500};
// id window = [[NSWindow alloc] initWithContentRect:frameRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO];
id window = ((id (*)(id, SEL, struct CGRect, int, int, int))objc_msgSend)(
msg_cls(cls("NSWindow"), sel("alloc")),
sel("initWithContentRect:styleMask:backing:defer:"),
frameRect,
NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable,
NSBackingStoreBuffered,
false
);
msg_id(window, sel("setTitle:"), msg_cls_chr(cls("NSString"), sel("stringWithUTF8String:"), "Pure C App"));
// [window makeKeyAndOrderFront:nil];
msg_ptr(window, sel("makeKeyAndOrderFront:"), nil);
// [app activateIgnoringOtherApps:YES];
msg_int(app, sel("activateIgnoringOtherApps:"), true);
msg(app, sel("run"));
}
Pure C cross-platform example: (Windows/macOS/Linux)
https://nappgui.com/en/demo/products.html
About macOS portability in pure C (updated to BigSur and M1 support):
https://nappgui.com/en/start/win_mac_linux.html#h2
I'm creating an application in pure C on Mac OSX. What I want is to create window in which my app will be stored.
Are you looking for a TTY window?
If so does your application need to create the window?
If not then you can simply write your pure C program and execute it from within Terminal - a TTY environment for "pure C".
If you want a double-clickable app you can write an AppleScript which will open Terminal and run your C. Something like:
tell application "Terminal"
do script "ex /tmp/test; exit"
end tell
This opens a Terminal window showing "ex" and when that quits will terminate the shell process (so no further commands can be typed), but it will not close Terminal itself - for that you will have to work harder.
If you do want you application to create the window itself you either need to write your own simple TTY window, you might find some classes you can use, or you might be able to borrow code from an open source terminal app such as iterm.
HTH

How to capture event "down" "up" for a keystroke or a mouse button in C

I found numerous examples that use either X11 or linux/input.h unfortunately I am on Cygwin where linux/input.h does not exist.
I would like a simple example that I can use to detect events such as:
Key down
Key up
Or
Mouse button down
Mouse button up
I would like to find a solution that can work on Cygwin/Linux and as optionally on Windows/OSX.
Is it possible?
So far I've found 1 solution that is using X11:
#include <stdio.h>
#include <X11/Xlib.h>
char *key_name[] = {
"first",
"second (or middle)",
"third",
"fourth", // :D
"fivth" // :|
};
int main(int argc, char **argv)
{
Display *display;
XEvent xevent;
Window window;
if( (display = XOpenDisplay(NULL)) == NULL )
return -1;
window = DefaultRootWindow(display);
XAllowEvents(display, AsyncBoth, CurrentTime);
XGrabPointer(display,
window,
1,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask ,
GrabModeAsync,
GrabModeAsync,
None,
None,
CurrentTime);
while(1) {
XNextEvent(display, &xevent);
switch (xevent.type) {
case ButtonPress:
printf("Button pressed : %s\n", key_name[xevent.xbutton.button - 1]);
break;
case ButtonRelease:
printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]);
break;
}
}
return 0;
}
Building with
gcc foo.c -lX11
Unfortunately the Xserver has to be launched startxwin& and the mouse pointer has to be inside a X server window. So this is not a good solution.
Another approach was to use ncurses but It seems states key-down, key-up are not possible.
The example below does not work on cygwin because conio.h is not POSIX:
#include <stdio.h>
#include <conio.h>
char ch;
void main(){
while(1){
if(kbhit()){ //kbhit is 1 if a key has been pressed
ch=getch();
printf("pressed key was: %c", ch);
}
}
}
conio.h is a C header file used mostly by MS-DOS compilers to provide
console input/output.[1] It is not part of the C standard library or
ISO C, nor is it defined by POSIX.
You seem to want to make a cross-platform program. I doubt you'll be able to resolve this problem with Linux-only libraries. What I suggest is to:
Ditch X in favor of Qt or GTK.
Make a module that listens to key events using facilities from Windows.h, compiled only if user is on Windows. Sooner or later you'll need to do that anyway for other stuff as your project grows.

mysterious crash after load_bitmap from Allegro

I am new to Allegro. We have to use it in our study.
I have a problem with my code, which should load a bitmap and print it.
#include <allegro.h>
int main( void )
{
allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);
BITMAP *Bild;
if( (Bild=load_bitmap("Spielfeld_Rand.bmp", NULL) ) == NULL )
{
allegro_message( "Error" );
return 1;
}
while( !key[KEY_ESC])
{
draw_sprite(screen, Bild, 0,0);
}
destroy_bitmap(Bild);
return 0;
}
END_OF_MAIN()
The Code chrashes. I do not see any error message, my screen turns black and i can't do anything. I also tried to enter the full path of the picture, but it wont help.
But if i remove the if arount the load_bitmap, the program aborts and return to the sceen.
Can anyone help me with this mysterious crash?
Thanks alot.
set_gfx_mode will change your screen resolution to 640x480 and show a black screen.
The manual says not to use allegro_message in graphics mode. It is probably been called and is locking up the program.
In text mode, allegro_message will put up a dialog box with "Error" in it. The program then won't exit until the ok is selected.
You should also call allegro_exit before exiting or your screen will be left at 640x480 resolution.

Resources