I’m running into my limits here again…
I’m just trying to understand conceptually how these native frameworks… work(!), and, how Haxe’s approach is different from other languages, say, Lua.
So, for Lua, it seems, there’s a super important C API which can either be used from within C (and super-sets of C) to call Lua functions, or from Lua to call C functions. So, for example, within a C app (say iOS or Android (via NDK?)), you can hook some events (say touch input) to Lua; Or, you could call a C function within Lua, after “registering” them.
(I glanced at Corona—I mean, uh, Solar2D?—on the ‘hub. Not only was I unable to follow the touch input control flow… I was surprised at the amount of native code!!.. )
For us, thank god (or St. Nicolas), we can easily make a class (wrapper? extern) with metadata (@:native, @:include) which tells the compiler to do it’s magic and use those @:native strings from the @:include file… Or so I thought.
Now looking at NME (chosen as an example ‘cause it has native in it’s name), I found the native code for each platform in the
project folder. It seems there’s a common
Stage file which is then inherited by each platform, so for SDL there’s a
SDL(2)Stage and for iOS there’s a
UIStageView. This seems to have the main iOS entry point (at the end of 2000 lines of code ) in a function that is never called here and passes a callback [function] which is stored here globally.
Similarly, in that same giant file, I found the touch input events that I was looking for, which eventually get handled by…!!?—: a mysterious input handler, which is set elsewhere.
…And, well, that’s that. I’m guessing those two things are called by Haxe…? (note: I only have my iPad on me, so, not easy to trace at the moment…). I haven’t figured out the mystery: how does Haxe intermingle with the native code(?).
(I did however stumble upon a rad
JNI class that writes java binding functions for Android on-the-fly…!!! )
I thought: unlike Lua, all Haxe applications must begin in Haxe, so, the control flow begins somewhere in Haxe, then, eventually calls the native code, which itself somehow creates the native main app/“view” (!) (
CreateMainFrame) and sets ups the Haxe input managers (
I just want to know how the control shifts between the native code and Haxe code. Some sort of global callback manager? Generally, I would guess: input goes from native to Haxe and output goes from Haxe to native. Right? So, touch input gets sent up and verticies get sent down. No?
The second mystery is shorter:
How do the languages compile down to machine code? Conceptually of course, for the lay-man.
“Lua is cross-platform since the interpreter is written in C,” says Wikipedia. “but Haxe can be compiled to effing anything and interpreted!,” Wiki continued…
“Lua programs are not interpreted directly from the textual Lua file, but are compiled into bytecode, which is then run on the Lua virtual machine. The compilation process is typically invisible to the user and is performed during run-time.”
So… anything written in C can call the Lua interpreter (tiny) and run the Lua part of the code? I’m not sure when it’s turned into bytecode or thrown into a VM, but okay… whatever. Sounds like a tiny version of Java’s JVM, or even Flash!
Whereas Haxe—well, let’s continue using the iOS target as an example—compiles down to… C++ (via hxcpp)?? (—I didn’t know C++ works with obj-c? I thought they were mutually exclusive super-sets?..) And then straight down to machine code… ?
So the main choice is to either use a transpiler (? hxcpp, hxjs, hxc(?)…) or a magical interpreter / bytecode / VM box thingy (? hashlink, neko…). Furthermore, hashlink has an option to convert it’s bytecode back up to C! (It’s so wild that such few people even made this… Dart n v8 needed a bunch of Google engineers!)
…And the reason Haxe and Lua frameworks perform well is because people write the high-performance parts (rendering) in native code(?), making use of whatever manual memory management. (I saw a few
gc_send_to_top_of_heap() being called in the native stage file… iirc after every input event)
And yet somehow those magical boxes can be optimized such that they’re faster than human-written transpiled code that gets natively compiled…
This is tough… but maybe it will aid another troubled mind who needs to understand the big picture…