hxcpp externs, extending a native cpp class from Haxe?

382 views
Skip to first unread message

Daniel Uranga

unread,
Dec 10, 2015, 12:05:04 AM12/10/15
to haxe...@googlegroups.com
Its possible, using hxcpp externs, to extend a cpp class with virtual
methods implementing those methods with Haxe-generated code?

Specifically this class:
https://github.com/erincatto/Box2D/blob/master/Box2D/Box2D/Common/b2Draw.h#L35

and extend that one to create an Haxe debug draw class that can get
called from the cpp side (thus calling the haxe-generated code)

Hugh

unread,
Dec 14, 2015, 12:01:24 AM12/14/15
to Haxe
Hi,
No, this is not really going to work out easily.

What I suggest is to create a delegate class in normal cpp that extends the b2Draw class, say Haxeb2Draw.
From haxe code (using externs) create an instance of Haxeb2Draw and, pass in a Handler which has the appropriate functions on it.
Then, for each of the virtual functions, have the Haxeb2Draw directly call the appropriate methods on the Handler class.
A couple of tips:
Store the instance of the handler class in an "AutoGCRoot" in the Haxeb2Draw class.  This means the handler will stay alive as long as it is needed.  Then, in the destructor of the   Haxeb2Draw, delete the AutoGCRoot, allowing the handler to be collected.
Put the implementation of the Handler class next to your hx code, and make sure the build.xml files compiles it all in together.  This will help keep it  in sync with your Handler class.

I have glossed over these details, but please ask if you want to go down this path an need more info.

Hugh

Daniel Uranga

unread,
Dec 14, 2015, 11:43:32 AM12/14/15
to haxe...@googlegroups.com
Thanks Hugh! yes I was going that path.

How I pass the handler class and call methods from it? I was tinking
of passing the Haxe functions and use something like val_call.

If everything goes ok I will try to document this as well as possible
and maybe it can serve as an example of how to use all this hxcpp
techniques.
> --
> To post to this group haxe...@googlegroups.com
> http://groups.google.com/group/haxelang?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Haxe" group.
> For more options, visit https://groups.google.com/d/optout.

Hugh

unread,
Dec 15, 2015, 12:12:42 AM12/15/15
to Haxe
If you use the cppInclude method, the wrapper code will be able to "see" the definition of the haxe code and call it diectly. eg HaxeDraw.hx:
@:cppInclude("./ExternalDraw.cpp")
class HaxeDraw extends nme.display.Sprite
{
   
public function new()
   
{
     
super();
      untyped __cpp__
("MakeExternalDraw(this)");
   
}

   
// External Api
   
public function beginFill(colour:Int) graphics.beginFill(colour);
   
public function endFill() graphics.endFill();
   
public function moveTo(x:Float, y:Float) graphics.moveTo(x,y);
   
public function lineTo(x:Float, y:Float) graphics.lineTo(x,y);

}

By using cppInclude, the file gets sucked right into the generated code.  Then, ExternalDraw.cpp might look something like:


class ExternalDraw
{
public:
   
virtual ~ExternalDraw() { }
   
virtual void drawSquare(int col, double x, double y, double w, double h) = 0;
};

void DoDraw(ExternalDraw *draw)
{
   draw
->drawSquare(0xff0000,10,10,100,100);
   draw
->drawSquare(0x00ff00,50,50,200,200);
}

class HaxeDrawImpl : public ExternalDraw
{
public:
   
::HaxeDraw haxeDraw;

   
HaxeDrawImpl(::HaxeDraw inHandle)
   
{
      haxeDraw
= inHandle;
     
GCAddRoot( (hx::Object **)&haxeDraw.mPtr );
   
}
   
~HaxeDrawImpl()
   
{
     
GCRemoveRoot( (hx::Object**) &haxeDraw.mPtr );
   
}

   
void drawSquare(int col, double x, double y, double w, double h)
   
{
      haxeDraw
->beginFill(col);
      haxeDraw
->moveTo(x,y);
      haxeDraw
->lineTo(x+w,y);
      haxeDraw
->lineTo(x+w,y+h);
      haxeDraw
->lineTo(x,y+h);
      haxeDraw
->lineTo(x,y);
      haxeDraw
->endFill();
   
}
};


void MakeExternalDraw(::HaxeDraw inHandle)
{
   
HaxeDrawImpl *haxeDraw = new HaxeDrawImpl(inHandle);
   
DoDraw(haxeDraw);
   
delete haxeDraw;
}




Here it simply has a HaxeDraw instance. The other functions will be different obviously - you may need some b2 context to set the debug draw on - you can pass this in with exerns into the constructor.

Hugh

Daniel Uranga

unread,
Dec 16, 2015, 12:12:13 AM12/16/15
to haxe...@googlegroups.com
Thanks a lot Hugh, will work with this.

Daniel Uranga

unread,
Dec 20, 2015, 8:47:39 AM12/20/15
to haxe...@googlegroups.com

PSvils

unread,
Dec 20, 2015, 8:57:13 AM12/20/15
to Haxe
Do you have any comparison of this with NAPE?

Daniel Uranga

unread,
Dec 20, 2015, 9:07:22 AM12/20/15
to haxe...@googlegroups.com
Nope, theoretically the performance of box2d-linc should be exactly
the same as regular Box2d on C++, I dont know how that compares to
Nape.

PSvils

unread,
Dec 20, 2015, 9:13:54 AM12/20/15
to Haxe
Okay, yeah makes sense! Super nice working on this linc lib though, will have to check it out!

Hugh

unread,
Dec 20, 2015, 11:32:12 PM12/20/15
to Haxe
Really nice example, well done.  I'm would be very interested to see a comparison to the haxe version - in a physics limited case, rather than a line-render limited case.

Hugh
Reply all
Reply to author
Forward
0 new messages