HXCPP: Passing function pointer to C++

398 views
Skip to first unread message

KlaxonCow

unread,
Nov 6, 2015, 7:29:32 PM11/6/15
to Haxe
Now that I've got my Haxe code and C++ code nicely statically linked together, I've hit a slight snag.

I need to pass a function pointer to the C++ code, which the C++ code will store and call back later.

My Haxe code looks something like this:
public inline function setFunc(func:Int->Void):Void
{        
    untyped __global__
.CoreSetFunc(func);
}

And Haxe compiles this into the following C++ code (with the stack-marking code removed here for clarity):
Void Core_obj::setFunc(Dynamic func)
{
   
::CoreSetRender(func);
   
return null();
}

As you can see, it's changed the "Int->Void" function pointer into a "Dynamic" type, so my C++ code is receiving a "Dynamic" type.

The question is, how do I cleanly and properly call the function - passing that "int" parameter - that's wrapped up inside that "Dynamic" type?

I can just directly call "func(10);" and the function executes. But when I trace the parameter passed to it, it's not "10" as expected, but is zero.

(I also experimented a little to try to work out what was going on and called "func(10, 10);" - yes, this is quite wrong, as the function only takes one parameter and I'm giving it two - and the interesting thing is that the function does then receive "10" as the parameter. But this isn't a proper solution, of course, because I'm doing it wrong and while it works in one place, in another place, it causes a segmentation fault.)

Is there some method of "Dynamic" that allows me to call the function wrapped inside it, passing the parameter? Or, failing that, some way to safely cast the "Dynamic" into the "void (*)(int)" type that C++ understands?

(And is there any calling conventions / stack protocol stuff I need to be aware of? The "Int->Void" functions passed to the C++ code are always static functions. No "this" pointer is involved here.)

Fernando Serboncini

unread,
Nov 6, 2015, 9:35:49 PM11/6/15
to Haxe
I think I've solved a similar problem by passing my own C++ function as a callback and making THAT function call the Haxe function.

--
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.

KlaxonCow

unread,
Nov 10, 2015, 7:38:48 AM11/10/15
to Haxe
I solved the problem by rearranging things a little.

The C++ code now directly calls a new fixed static Haxe function, rather than a pointer to a Haxe function, and then that fixed Haxe function handles the function pointer stuff on the Haxe side.

So the Haxe side of things now looks more like this:

private static var theFunc:Int->Void = null;

public
inline function setFunc(func:Int->Void):Void
{        
    theFunc = func;
}

public static function CallFunc(param:Int):Void
{
   
if (theFunc != null)
   
{
        theFunc
(param);
   
}
}

And the C++ code now just directly calls "CallFunc(10);", which is an actual fixed static function (not a pointer to a function) that the C++ can be statically linked to it in the linking process, as per usual.

Just needed to sort out the include paths a little bit, so the C++ can see the generated ".h" file for the Haxe code and make sure that, in the makefile, Haxe runs first because the C++ now depends on the generated code.


Basically, I moved the function pointer stuff to all be on the Haxe side of things, as Haxe comprehends how to deal with pointers to its own functions properly and the C++ just defers to this new function to handle the call to the function pointer on its behalf.

This works, but it still feels like a bit of an unnecessary hack in that there's an extra function call there that wouldn't need to be made, if I could just work out how to "unwrap" the function pointer from the "Dynamic" type to use it directly from the C++ code. It'll do, though.

Thanks for making me think laterally about re-arranging things. Not that I quite did it the way you suggested, but it got me thinking in the right direction to find this alternative solution instead.

(Perhaps, once I've got everything else working, I'll come back to this and try to fathom how to make the "Dynamic" work, when I polish up my code at the end, to make things nicer and more optimised.)

Hugh

unread,
Nov 16, 2015, 12:19:21 AM11/16/15
to Haxe
Your initial solution should have worked - dynamic has  "inline ::Dynamic operator()(const Dynamic &inArg0) ", so your int (10) should get converted to a dynamic and passed to the function, and then converted back into an int.

Some possibilities why this did not work - you called it from a non-haxe thread, or you did not store the callback in a GC root (although, this would probably crash, rather than give 0)

You can pass a raw function pointer (to static haxe function) to cpp code using cpp.Function.fromStaticFunction( YourClass.yourFunction ) but this does not work for closures.

Hugh
Reply all
Reply to author
Forward
0 new messages