-
-
Save nadako/c8aec20c2a7751348f91 to your computer and use it in GitHub Desktop.
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 |
That's pretty cool, man! So, as long as we have access to the header files, we can avoid CFFI?
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 😄
@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 :)
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.
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.
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.
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.
Now we only need to autogenerate that!