What is expected way(best way?) to pass buffer into haxe static library function from c++ container?

163 views
Skip to first unread message

Tiger Chan

unread,
Jun 8, 2017, 9:40:14 AM6/8/17
to Haxe
I have build a c++ static library libWorld.a using haxe, and include it from c++
Now I want to pass a unsigned char* (better to keep using same address instead of copy value) into a function from static library as a parameter.
I found this example and tried with no luck, got segfault when call alloc_buffer_len(100);

Tiger Chan

unread,
Jun 8, 2017, 10:20:32 PM6/8/17
to Haxe
I guess segfault is because i have not include hxcpp source code or library.
How to include hxcpp in a static_link build? I have given flag "-lib hxcpp" but no any different of output file size.

Hugh

unread,
Jun 9, 2017, 12:41:26 AM6/9/17
to Haxe
I'm not 100% sure what you are trying to do here.  Let me assume that that some larger, native, c++ program calls into your hxcpp code.  Then at some stage, the hxcpp code wants to callback into the native program and pass a buffer.

You can do this by declaring an class similar to this:
@:cppFileCode('
extern void onHaxeData(unsigned char *inData);
'
)
class Sender
{
   
@:native("onHaxeData")
   
@:extern public static function onHaxeData(ptr:cpp.Star<cpp.UInt8>) { }

   
public static function sendHaxeData(data:haxe.io.BytesData)
   
{
      onHaxeData
( cast cpp.NativeArray.address(data,0) );
   
}
}



and use it like:

Sender.sendHaxeData( haxe.io.Bytes.ofString("Hello").getData() );

This will be zero-copy (ie, memory alias), although in this case the "ofString" command will do a copy.

If you try to link this code as is, you will get an unresolved for 'onHaxeData'.  This is what your enclosing native app will provide.

Hugh

Tiger Chan

unread,
Jun 9, 2017, 3:51:02 AM6/9/17
to Haxe
Sorry I have not describe clearly.
some larger, native, c++ program calls into my hxcpp code with buffer

Some pseudo code in c++ I expecting

int main(){
   
unsigned char* data = "hello";

   
::com::project::Sender* sender = new ::com::project::Sender();

   
Sender->processBuffer(data);

}

Hugh

unread,
Jun 12, 2017, 12:43:24 AM6/12/17
to Haxe
If your extenal code does not want to "#include <hxcpp.h>", you can do it like this:

@:cppFileCode('
// cppFileCode can "see" the definition of Receiver, and can put
//   stuff in the global namespace
void setDataToHaxe(unsigned char *inData, int length)
{
   Receiver_obj::onNativeData(inData, length);
}

// This is what would go in your native code:
extern void setDataToHaxe(unsigned char *inData, int length);

void fakeNative()
{
   setDataToHaxe((unsigned char *)"hello", 6);
}

'
)
class Receiver
{
   
@:keep public static function onNativeData(ptr:cpp.Star<cpp.UInt8>, length:Int)
   
{
      trace
("Got data " + ptr + "*" + length);

     
// Wrap in haxe.io.Bytes for use with internal APIs...
     
var data = new Array< cpp.UInt8 >();
      cpp
.NativeArray.setUnmanagedData(data,cast ptr, length);
     
var bytes = haxe.io.Bytes.ofData(data);

      trace
( bytes.toString() );
   
}

   
@:extern @:native("fakeNative")
   
public static function runFakeNative() : Void { }

   
public static function main()
   
{
      runFakeNative
();
   
}
}



Here, you use cppFileCode to create an extern function in the global namespace that is easy for your native code to call by using an "extern" function definition.
The function can also "see" the haxe code, so it can make a call into haxe directly.
If you wrap the pointer in a haxe.io.Bytes using unmanagedData, you can use all the normal APIs while also avoiding the byte copy.

Hugh
Reply all
Reply to author
Forward
0 new messages