Skip to content

Instantly share code, notes, and snippets.

@nadako nadako/Main.hx
Created Jun 24, 2015

Embed
What would you like to do?
Haxe + SDL = native love \o/
class Main {
static function main() {
Sdl.init(Sdl.INIT_EVERYTHING);
var win = Sdl.createWindow("Hello", 100, 100, 800, 600, Sdl.WINDOW_OPENGL);
var ren = Sdl.createRenderer(win, -1, Sdl.RENDERER_ACCELERATED);
var bmp = Sdl.loadBMP("test.bmp");
var tex = Sdl.createTextureFromSurface(ren, bmp);
Sdl.freeSurface(bmp);
for (i in 0...3) {
Sdl.renderClear(ren);
Sdl.renderCopy(ren, tex, cast 0, cast 0);
Sdl.renderPresent(ren);
Sdl.delay(1000);
}
}
}
import cpp.ConstCharStar;
@:include("./SDLSupport.h")
@:buildXml('<target id="haxe"><lib name="../SDL2-2.0.3/lib/x86/SDL2.lib"/></target>')
extern class Sdl {
@:native("SDL_INIT_EVERYTHING")
static var INIT_EVERYTHING(default,null):InitFlag;
inline static var WINDOW_NONE:CreateWindowFlag = cast 0;
@:native("SDL_WINDOW_OPENGL")
static var WINDOW_OPENGL(default,null):CreateWindowFlag;
inline static var RENDERER_NONE:CreateRendererFlag = cast 0;
@:native("SDL_RENDERER_ACCELERATED")
static var RENDERER_ACCELERATED(default,null):CreateRendererFlag;
@:native("SDL_Init")
static function init(flags:InitFlag):Int;
@:native("SDL_CreateWindow")
static function createWindow(title:ConstCharStar, x:Int, y:Int, w:Int, h:Int, flags:CreateWindowFlag):WindowPointer;
@:native("SDL_CreateRenderer")
static function createRenderer(win:WindowPointer, index:Int, flags:CreateRendererFlag):RendererPointer;
@:native("SDL_LoadBMP")
static function loadBMP(file:ConstCharStar):SurfacePointer;
@:native("SDL_CreateTextureFromSurface")
static function createTextureFromSurface(renderer:RendererPointer, surface:SurfacePointer):TexturePointer;
@:native("SDL_FreeSurface")
static function freeSurface(surface:SurfacePointer):Void;
@:native("SDL_RenderClear")
static function renderClear(renderer:RendererPointer):Int;
@:native("SDL_RenderCopy")
static function renderCopy(renderer:RendererPointer, texture:TexturePointer, srcRect:RectPointer, dstRect:RectPointer):Int;
@:native("SDL_RenderPresent")
static function renderPresent(renderer:RendererPointer):Void;
@:native("SDL_Delay")
static function delay(ms:cpp.UInt32):Void;
}
abstract InitFlag(cpp.UInt32) {
@:op(A|B) static function _(a:InitFlag, b:InitFlag):InitFlag;
}
abstract CreateWindowFlag(cpp.UInt32) {
@:op(A|B) static function _(a:CreateWindowFlag, b:CreateWindowFlag):WindowPointer;
}
abstract CreateRendererFlag(cpp.UInt32) {
@:op(A|B) static function _(a:CreateRendererFlag, b:CreateRendererFlag):CreateRendererFlag;
}
@:native("::cpp::Reference<SDL_Window>")
extern class WindowPointer {}
@:native("::cpp::Reference<SDL_Renderer>")
extern class RendererPointer {}
@:native("::cpp::Reference<SDL_Surface>")
extern class SurfacePointer {}
@:native("::cpp::Reference<SDL_Texture>")
extern class TexturePointer {}
@:native("::cpp::Reference<SDL_Rect>")
extern class RectPointer {}
#include "SDL2-2.0.3/include/SDL.h"
#undef main
@nadako

This comment has been minimized.

Copy link
Owner Author

commented Jun 24, 2015

Now we only need to autogenerate that!

@fullofcaffeine

This comment has been minimized.

Copy link

commented Jun 25, 2015

That's pretty cool, man! So, as long as we have access to the header files, we can avoid CFFI?

@porfirioribeiro

This comment has been minimized.

Copy link

commented Jun 26, 2015

This is great! Why use ndll CFFI layer when you can do native calls, targeting CPP? 😔

For auto generate externs from headers maybe something like http://www.swig.org/ will help.

I remember that being used to generate FreeBasic headers from C 😄

@underscorediscovery

This comment has been minimized.

Copy link

commented Jul 2, 2015

@porfirioribeiro CFFI still works with neko, these do not (and can't)

@nadako Nice gist! Now I have to fast track an announcement for a set of libraries (including SDL) which i've already bound 😳 hah

There are some problems with autogenerating btw, if you want the API to be "haxe friendly" (for example SDL_GetWindowSize( window, int* w, int* h ), a better alternative is GetWindowSize(window):{w:Int, h:Int} which requires specific rules about the c api's that don't fit haxe usage. Another example: stack values (now better with cpp.Reference but can still be a problem) and allocations in general skipping GC - these type of details need care and attention to be stable.

Anyway I'll make a blog post about this - aside from some few endpoints I've already bound the whole of SDL for use with "just" haxe/hxcpp :)

@nadako

This comment has been minimized.

Copy link
Owner Author

commented Aug 24, 2015

oh, this gist has comments! too bad I didn't receive any notifications :-(

yeah probably autogenerating is not the way here, but we can greatly simplify the extern class syntax through macros. In the other version I played with, I made a @:build macro that automatically inserts @:native metadatas and static modifiers for methods and vars in the extern class, so it's quite easy to write.

@nadako

This comment has been minimized.

Copy link
Owner Author

commented Aug 24, 2015

As for "haxe-friendliness". I would make a plain 1-to-1 SDL API bindings and then add an additional layer over that that wraps stuff into classes and structures.

@Aurel300

This comment has been minimized.

Copy link

commented Sep 22, 2016

Thank you! You just saved me an hour or two of figuring out external .cpp code with haxe and SDL2, etc … This works pretty much out of the box.

@bckpkol

This comment has been minimized.

Copy link

commented May 23, 2019

Line 62 is probably wrong.
@:op(A|B) static function _(a:CreateRendererFlag, b:CreateRendererFlag):CreateRendererFlag;
should be
@:op(A|B) static function _(a:CreateRendererFlag, b:CreateRendererFlag):RendererPointer;
by analogy with the line 58
@:op(A|B) static function _(a:CreateWindowFlag, b:CreateWindowFlag):WindowPointer;
However, I'm not sure. I'm not so familiar with Haxe yet to understand this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.