I'm creating an OpenFL extension for a mobile advertising SDK, and I'm having difficulty figuring out some CFFI stuff.
Basically, I'm trying to pass a Haxe object to C++, and then call a method on that object from C++. The purpose of this is as an event listener, so when something happens in C++, I will call a callback on that object to notify the Haxe code.
I know how to do this with Java using lime's JNI stuff for Android. That looks something like this using JNI type signatures:
var setCallbackListener = JNI.createStaticMethod("com.test.myextension", "setCallbackListener", "(Lorg/haxe/lime/HaxeObject;)V");
var listener = new MyCallbackListener(); //implements `onSomething`
setCallbackListener(listener); //pass the listener to the Java side
Then from the Java side, I can call the function onSomething like this:
public static void setCallbackListener(HaxeObject listener){
listener.call0("onSomething"); //call a function called "onSomething" with zero arguments
}
And that works, and it's how I'm doing it for Android. For iOS, I'm trying to do the same thing, but with hxcpp.
I know the general process for calling a C++ function from Haxe, using cpp.Lib.load in a similar way to the JNI api above. However, once I get a value type on the C++ side, I don't know how I can call a member function on it.
for example, say my C++ function looks like this:
#include <hx/CFFI.h>
static void setCallbackListener (value listener) {
//...
}
DEFINE_PRIM (setCallbackListener, 1);
How would I then call the function "onSomething" in listener?
After some digging I figured it out! Unfortunately, none of this seems to be documented at all, so I figured I'd post my findings here in case someone else wants to do the same thing.
Method 1
The hxcpp C API is apparently very similar to the Neko one, although not exactly the same. Still, the Neko documentation is a good starting point.
That page shows you how to call a function by using
val_call0,val_call1, etc. What it doesn't show you is how to obtain a reference to the function you want from an instance. To do that, you can use the functionsval_idandval_fieldtogether like this (this is for hxcpp, not sure if it also works for Neko):If the function took 2 arguments instead of one (for example), then you'd use
val_call2, and call it like this:There is also
val_callNwhich accepts an arbitrary amount of arguments. See the declaration here.Reference: https://github.com/HaxeFoundation/hxcpp/blob/master/project/libs/std/Socket.cpp#L1039
Method 2
Fortunately, there were only 3 results when I Googled "hxcpp val_call" (without quotes), and one of those links detailed this method.
Just read through that thread for a full explanation. That method would probably be preferred if you need better memory management, as it also shows how to tie in to the hxcpp GC from your C++.
Disclaimer
I couldn't find any actual documentation on
val_idandval_field, so it's possible that these methods aren't meant to be used externally and might change in a later version of hxcpp. I have no idea. ♂️