brson / rust-sdl

SDL bindings for Rust
MIT License
179 stars 52 forks source link

Issue running demo app in OSX 10.9 Mavericks #118

Closed janua closed 10 years ago

janua commented 10 years ago

I have compiled and installed rust on my machine, along with SDL 1.2.15 with homebrew.

The demo app compiles fine. But when I run it, it does nothing. It seems to be the call to sdl::video::set_video_mode that does not return a Result.

pnkfelix commented 10 years ago

I'm looking at this now.

From running under gdb and after doing catch throw, I see this backtrace before exiting:

...
(gdb) catch throw
Catchpoint 7 (throw)
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /Users/pnkfelix/Dev/Rust/rust-sdl/main 
Reading symbols for shared libraries . done
Catchpoint 7 (exception thrown).
Catchpoint 7 (exception caught), throw location unknown, catch location unknown, exception type unknown
0x00007fff8bd3f521 in __cxa_throw ()
(gdb) bt
#0  0x00007fff8bd3f521 in __cxa_throw ()
#1  0x00007fff8e83450c in objc_exception_throw ()
#2  0x00007fff8b8848dc in +[NSException raise:format:] ()
#3  0x00007fff86897b49 in _NSCreateWindowWithOpaqueShape2 ()
#4  0x00007fff86896340 in -[NSWindow _commonAwake] ()
#5  0x00007fff86854d82 in -[NSWindow _commonInitFrame:styleMask:backing:defer:] ()
#6  0x00007fff86853ecf in -[NSWindow _initContent:styleMask:backing:defer:contentView:] ()
#7  0x00007fff8685389f in -[NSWindow initWithContentRect:styleMask:backing:defer:] ()
#8  0x00000001003711f0 in -[SDL_QuartzWindow initWithContentRect:styleMask:backing:defer:] (self=0x102933eb0, _cmd=0x7fff870d340f, contentRect={origin = {x = 0, y = 0}, size = {width = 800, height = 600}}, styleMask=7, backingType=2, flag=0 '\000') at /Users/pnkfelix/Dev/Rust/rust-sdl/SDL-mirror/src/video/quartz/SDL_QuartzWindow.m:197
#9  0x000000010036dac4 in QZ_SetVideoWindowed (this=0x100815a00, current=0x10292fad0, width=800, height=600, bpp=0x101f1357c, flags=1073741825, save_gl=0 '\000') at /Users/pnkfelix/Dev/Rust/rust-sdl/SDL-mirror/src/video/quartz/SDL_QuartzVideo.m:1023
#10 0x000000010036c5db in QZ_SetVideoModeInternal (this=0x100815a00, current=0x10292fad0, width=800, height=600, bpp=32, flags=1073741825, save_gl=0 '\000') at /Users/pnkfelix/Dev/Rust/rust-sdl/SDL-mirror/src/video/quartz/SDL_QuartzVideo.m:1151
#11 0x000000010036bc47 in QZ_SetVideoMode (this=0x100815a00, current=0x10292fad0, width=800, height=600, bpp=32, flags=1073741825) at /Users/pnkfelix/Dev/Rust/rust-sdl/SDL-mirror/src/video/quartz/SDL_QuartzVideo.m:1229
#12 0x000000010035c05d in SDL_SetVideoMode (width=800, height=600, bpp=32, flags=1073741825) at /Users/pnkfelix/Dev/Rust/rust-sdl/SDL-mirror/src/video/SDL_video.c:683
#13 0x000000010018fa8e in _ZN3sdl5video14set_video_modeE (w=800, h=600, bpp=32, surface_flags={data_ptr = 0x101f13c54, length = 1}, video_flags={data_ptr = 0x101f13c3c, length = 1}) at video.rs:382
#14 0x00000001000011bb in _ZN4main4mainE () at main.rs:16
#15 0x00000001000f7a1c in task::bootstrap_green_task::closure ()
#16 0x00000001000d42b8 in rt::task::Task::run::closure ()
#17 0x00000001000de26c in rust_try ()
#18 0x00000001000f78d5 in task::bootstrap_green_task::hbb0150eeae2a78081bc::v0.10.pre ()
(gdb) 

I added some instrumentation to my local build of the SDL code, to wrap the NSWindow initWithContent call in a @try/@catch block and print out the exception reason before re-throwing it, i.e. something like this:

--- a/src/video/quartz/SDL_QuartzWindow.m
+++ b/src/video/quartz/SDL_QuartzWindow.m
@@ -193,8 +193,15 @@ static void QZ_SetPortAlphaOpaque () {

     [ [ NSNotificationCenter defaultCenter ] addObserver:self
         selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ];
-        
-    return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
+
+    @try {
+      return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ];
+    }
+    @catch (NSException *exception) {
+   printf("Hi world, got an exception\n");
+   printf("%s\n", [[exception reason] UTF8String]);
+   @throw;
+    }
 }

 @end

and I get this print out in response now:

Hi world, got an exception
Error (1000) creating CGSWindow on line 259

From searching about this error message on Google, it looks like this may be a problem that occurs when one attempts to create a window without first initializing a proper NSApplication instance. Not sure yet, I do not do much Mac OS X gui hacking. (Indeed, my reason for trying to use something like rust-sdl is the hope that someone else would have already resolved all issues like this.)

edit: the above results are for my Mac OS X 10.8 machine. I would like to know if others have had success running the rust-sdl demo app on any Mac OS X dev box.

pnkfelix commented 10 years ago

I've got something plausible working now, but boy it is a bit hacky. I guess I'll note it here in case other people discover this in the future.

SDL on OS X (and maybe in general) really wants to take over the intialization of your application and then hand control off to you. In C land it does this, I think, via preprocessor trickery to make your definition of main actually turn into SDL_main (and then you are supposed to compile with arguments to link in src/main/macosx/SDLMain.m). Luckily we've got enough machinery in rustc to integrate with all this semi-cleanly, assuming that one is comfortable firing up the runtime "by hand":


$(SDL_DEMO): $(SDL_DEMO_SRC) $(SDL_LIB) $(MK_FILES)
    rustc -g $< -L. -L/Users/pnkfelix/opt/sdl-release-1.2.15-dbg-nopt/lib -C link-args="-I$(HOME)/opt/sdl-release-1.2.15-dbg-nopt/include/SDL -framework CoreFoundation -framework CoreGraphics -framework AppKit SDL-mirror/src/main/macosx/SDLMain.m  "
#[no_main]; // this is new

extern crate sdl;

use std::rand::Rng;
use std::rand;

pub fn real_main() { // this is renamed
    sdl::init([sdl::InitVideo]);
    sdl::wm::set_caption("rust-sdl demo - video", "rust-sdl");
    ...
}
#[no_mangle]
pub extern "C" fn SDL_main(argc: int, argv: **u8) {
    green::start(argc, argv, real_main);
}

Sorry for not putting up a more coherent explanation, these are more notes on the process I used and the results I got than anything else. If I get a chance I will try to put up a proper pull-request with a separate sdl-demo tailored to OS X machines.


update: the above code fires up the M:N threading runtime, libgreen (the green::start call). I do not know how to handle UI events in that context. When I change the code to fire up the 1:1 threading runtime, libnative, then things work quite swimmingly.