Reputation: 363
I have a cli written in Haxe and compiled to a binary via C++ (hxcpp). I would like to use ncurses in it. I have worked with ncurses in C and I've worked with JS externs in Haxe but I'm can't figure out the Haxe/C++ documentation to connection the two together.
I haven't used much more of the HXCPP compiler than the basic haxe command (ie not build files etc), à la:
haxe -lib somelib -cp src --cpp bin/cpp path.to.Main
Basically, I can work with all custom code, but am struggling on externals. So I'm not entirely sure how many steps I am missing towards my goal. But I can see a few major obstacles.
cc -lncurses -o out [etc...]
in a Makefile.I know this is basically asking for a mini-tutorial, but I can't find examples or documentation that I can put together to accomplish this specific goal.
Thanks for any help you can lend.
Upvotes: 4
Views: 1381
Reputation: 439
HXCPP uses an xml-based build system. When you launch haxe -cp src --cpp bin/cpp path.to.Main
:
Build.xml
is produced in the output directory, i.e. bin/cpp/Build.xml
;Build.xml
with the global default xml definitions and then calling the compiler toolchain(s).You can inject compiler flags, libraries to link, includes directories, etc., through the @:buildXml
metadata, as described on the manual:
@:buildXml("
<target id='haxe'>
<lib name='-lncurses' if='linux'/>
<lib name='ncurses.lib' if='windows'/>
</target>
")
class Main{ ...
These tags will be appended to the project Build.xml
. The haxe
target is the default target. Keep in mind that every toolchain (MSVC, gcc, Xcode, etc.) has its own syntax. You can see examples in the build.xml of cross-platform low-level projects like Systools or Lime.
You can add -D HXCPP_VERBOSE
to the haxe command line to see which commands are actually launched: haxe -D HXCPP_VERBOSE -cp src --cpp bin/cpp path.to.Main
.
As for externs, the simpler case is:
@:cppFileCode()
block; everything you write here is pasted as-is in the generated cpp file;@:native("nameOfTheCppFunction")
, and the build system will join them together. @:cppFileCode("
#include <ncurses.h>
void nativeCppTest(){
/* here goes your ncurses code */
return;
}
")
class Main{
public static function main()
{
myCppTest();
}
@:native("nativeCppTest")
extern static function myCppTest():Void;
}
If you open the generated file (in this case bin/cpp/src/Main.cpp
) you'll see that the haxe myCppTest()
call is changed to its native version nativeCppTest()
.
If you would like to pass function arguments, and receive return values, you'll have to wrap those using the cpp.*
standard library types. For example:
@:cppFileCode("
#include <ncurses.h>
void nativeCppTest(const char* myString){
/* here goes your ncurses code */
return;
}
")
class Main{
public static function main()
{
myCppTest("print this");
}
@:native("nativeCppTest")
extern static function myCppTest(myString:cpp.ConstCharStar):Void;
}
Some of the conversions will be automatic (like, in this case, from a constant string to ConstCharStar), some will require an explicit cast
; if you need to pass pointers to the C++ code, you can get it via cpp.RawConstPointer.addressOf(<haxe object>)
(or RawPointer
if not const):
public static function main()
{
var myString:String = "print this";
myCppTest(cast cpp.RawConstPointer.addressOf(myString));
}
Useful references:
Upvotes: 2