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

瀏覽次數:163 次
跳到第一則未讀訊息

Tiger Chan

未讀,
2017年6月8日 上午9:40:142017/6/8
收件者: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

未讀,
2017年6月8日 晚上10:20:322017/6/8
收件者: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

未讀,
2017年6月9日 凌晨12:41:262017/6/9
收件者: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

未讀,
2017年6月9日 凌晨3:51:022017/6/9
收件者: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

未讀,
2017年6月12日 凌晨12:43:242017/6/12
收件者: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
回覆所有人
回覆作者
轉寄
0 則新訊息