Passing bytes from c++ to haxe

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