Passing bytes from c++ to haxe

Hey,

I am working on a native extension at the moment and am trying to pass some bytes from c++ back to haxe. On the c++ end, I have a int16_t array that represents 16bit PCM audio data and in haxe I need an instance of haxe.io.Bytes that contains the same information as the int16_t array. I haven’t found much documentation on that topic which is why I am asking here, what the best way of doing that would be. Down below you can see how I at least managed to pass some data, obviously not correct though.

C++

extern "C" void pass_data_back(unsigned long length, const int16_t* data) {
	value arr = alloc_array(length);
	for (int i = 0; i < length; i++) 
	{	
		val_array_set_i(arr, i, alloc_int (data[i]));	
	}
	val_call1(cb_onaudiodata->get(), arr);
}

Haxe

function cb_onaudiodata(arr:Dynamic)
{
	var bytes = Bytes.alloc(arr.length);
	for(i in 0...arr.length)
	{
		bytes.setInt32(i, arr[i]);
	}
}

I think you can do something like this:

Header

#include <hx/CFFI.h>

Creating a buffer

value bytes;
int length = 100;

unsigned char* data;

buffer b = alloc_buffer_len (length);
data = (unsigned char*)buffer_data (b);

if (data) {
    
    bytes = buffer_val (b);
    
} else {
    
    bytes = alloc_raw_string (length);
    data = (unsigned char*)val_string (s);
    
}

Filling the buffer with data

for (int i = 0; i < length; i++) {
    
    data[i] = i;
    
}

Returning it to Haxe

value object = alloc_empty_object ();
alloc_field (object, val_id ("b"), bytes);
alloc_field (object, val_id ("length"), alloc_int (length));

return object;

On the Haxe C++ target, I think you can return the bytes value directly back to Haxe, and treat it as a haxe.io.Bytes instance. Something like that. In Lime, we support both HXCPP and Neko (and will support more virtual machines in the future), so it is not possible to pass it back directly. This is also where the alloc_raw_string comes in, as some targets (IE, Neko) don’t support the buffer type. We use something like the above, where we allocate an empty Haxe object and set it’s fields. We then use this to create a haxe.io.Bytes instance on the Haxe side:

var data = make_cffi_call (); // the CFFI method that is returning the object
var bytes = @:privateAccess new Bytes (data.length, data.b);

The Lime array buffer types, as well as the OpenFL ByteArray type, support conversion from Haxe Bytes. They are abstracts, so it’s a lightweight conversion just to change how you read the data – it does not perform a copy. Once you have your Bytes, you can treat it how you feel most comfortable

var byteArray:ByteArray = cast bytes;

In Lime, we cache the val_id calls to save a bit of performance, but I believe the above code is pretty much the gist of what we use