379 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			379 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
|  | package tests; | ||
|  | 
 | ||
|  | import NativeGen; | ||
|  | import cpp.NativeGc; | ||
|  | import cpp.Stdlib; | ||
|  | import cpp.Pointer; | ||
|  | import cpp.RawPointer; | ||
|  | import cpp.UInt8; | ||
|  | using cpp.NativeArray; | ||
|  | using cpp.NativeString; | ||
|  | 
 | ||
|  | @:unreflective | ||
|  | @:native("CVec") | ||
|  | extern class Vec { | ||
|  |    public var x:Float; | ||
|  |    public var y:Float; | ||
|  |    public var z:Float; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | @:unreflective | ||
|  | @:structAccess | ||
|  | @:native("CVec") | ||
|  | extern class VecStructAccess { | ||
|  |    public var x:Float; | ||
|  |    public var y:Float; | ||
|  |    public var z:Float; | ||
|  | 
 | ||
|  |    @:native("new CVec") | ||
|  |    public static function create(val:Float) : Pointer<VecStructAccess>; | ||
|  | 
 | ||
|  |    public function set99(ioVec:VecStructAccess):Void; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | @:unreflective | ||
|  | @:native("cpp::Struct<CVec>") | ||
|  | extern class VecStruct { | ||
|  |    public var x:Float; | ||
|  |    public var y:Float; | ||
|  |    public var z:Float; | ||
|  | } | ||
|  | 
 | ||
|  | @:native("::SomeStruct") | ||
|  | extern class Native_SomeStruct { | ||
|  |     var data:RawPointer<cpp.UInt8>; | ||
|  |     var dataLength:Int; | ||
|  | 
 | ||
|  |     inline function getDataBytes():haxe.io.Bytes { | ||
|  |         var bdata:haxe.io.BytesData = []; | ||
|  |         cpp.NativeArray.setData(bdata, cast data, dataLength);  // Null Function Pointer | ||
|  |         return haxe.io.Bytes.ofData(bdata); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline function getUnmanagedDataBytes():haxe.io.Bytes { | ||
|  |         var bdata:haxe.io.BytesData = []; | ||
|  |         cpp.NativeArray.setUnmanagedData(bdata, cast data, dataLength);  // Null Function Pointer | ||
|  |         return haxe.io.Bytes.ofData(bdata); | ||
|  |     } | ||
|  | 
 | ||
|  | } | ||
|  | @:native("::cpp::Reference<SomeStruct>") | ||
|  | extern class SomeStructRef extends Native_SomeStruct {} | ||
|  | @:native("::cpp::Struct<SomeStruct>") | ||
|  | extern class SomeStruct extends SomeStructRef {} | ||
|  | 
 | ||
|  | class IntHolder | ||
|  | { | ||
|  |    public var ival:Int; | ||
|  | 
 | ||
|  |    public function new(inVal:Int = 1) ival = inVal; | ||
|  | } | ||
|  | 
 | ||
|  | @:headerCode('
 | ||
|  | struct CVec{ | ||
|  |    CVec(double inX=0) : x(inX), y(inX), z(inX) { } | ||
|  | 
 | ||
|  |    double x; | ||
|  |    double y; | ||
|  |    double z; | ||
|  | 
 | ||
|  |   void set99(CVec &ioVex) { ioVex.x=99; } | ||
|  | }; | ||
|  | 
 | ||
|  |   struct SomeStruct { | ||
|  |      SomeStruct() : data((unsigned char *)"Hi!"), dataLength(3) { } | ||
|  | 
 | ||
|  |      unsigned char *data; | ||
|  |      int dataLength; | ||
|  |   }; | ||
|  | ')
 | ||
|  | @:cppFileCode('
 | ||
|  |   int callPointer(CVec *) { return 5; } | ||
|  | ')
 | ||
|  | class TestPtr extends haxe.unit.TestCase{ | ||
|  |     | ||
|  |    /* | ||
|  |     Alternate version | ||
|  |    @:generic | ||
|  |    public static inline function malloc<T>(size:Int) : cpp.Pointer<T>{ | ||
|  |       var p : cpp.RawPointer<cpp.Void> = untyped __cpp__("malloc({0})",size); | ||
|  |       return cast cpp.Pointer.fromRaw( cast p ); | ||
|  |    } | ||
|  |    */ | ||
|  |     | ||
|  |     public function testMalloc() { | ||
|  |       var a : Pointer<Vec> = Stdlib.malloc( Stdlib.sizeof(Vec) ); | ||
|  |       assertTrue( a!=null ); | ||
|  |       assertTrue( a.raw!=null ); | ||
|  |       a.ptr.x = 66; | ||
|  |       assertTrue( a.ptr.x == 66 ); | ||
|  |       Stdlib.free(a); | ||
|  |    } | ||
|  |     | ||
|  |     public function testExtened() { | ||
|  |       var test = NativeGc.allocateExtended( TestPtr, Stdlib.sizeof(Int) * 5 ); | ||
|  |       var a : Pointer<Int> = cast Pointer.endOf(test); | ||
|  |       for(i in 0...5) | ||
|  |          a.setAt(i,i); | ||
|  |       for(i in 0...5) | ||
|  |          assertTrue( a.postIncRef() == i ); | ||
|  |    } | ||
|  | 
 | ||
|  |    function test9194() { | ||
|  |       // will fail during C++ compile | ||
|  |       var buffer: cpp.RawPointer<cpp.Void> = null; | ||
|  |       var floatBuffer: cpp.RawPointer<cpp.Float32> = cast buffer; | ||
|  |       // generates incorrect: float* floatBuffer = buffer | ||
|  |       // the lack of native casting means the compiler throws an error here | ||
|  | 
 | ||
|  |       var buffer: cpp.Star<cpp.Void> = null; | ||
|  |       var floatBuffer: cpp.Star<cpp.Float32> = cast buffer; | ||
|  |       // generates correct: float* floatBuffer = ( (float*) buffer )  | ||
|  | 
 | ||
|  |       assertTrue(floatBuffer==null); | ||
|  |    } | ||
|  | 
 | ||
|  | 
 | ||
|  |    public function testNull() { | ||
|  |       var nullP : Pointer<Vec> = null; | ||
|  |       var nullRawP = nullP.raw; | ||
|  |       assertTrue( nullP==null ); | ||
|  |       assertTrue( null==nullP ); | ||
|  |       assertFalse( nullP!=null ); | ||
|  |       assertTrue( nullRawP==null ); | ||
|  |       assertFalse( nullRawP!=null ); | ||
|  |       nullRawP = null; | ||
|  |       assertTrue( nullRawP==null ); | ||
|  |    } | ||
|  | 
 | ||
|  |    private function anonOf(d:Dynamic) : Dynamic return {ptr:d}; | ||
|  | 
 | ||
|  |    public function testStructAccess() { | ||
|  |       var e = VecStructAccess.create(1); | ||
|  |       var tmp = e.ptr; | ||
|  |       var tmp1 = e.ref; | ||
|  |       tmp.set99(tmp1); | ||
|  |       assertTrue(e.ptr.x==99); | ||
|  |    } | ||
|  | 
 | ||
|  |    @:native("callPointer") @:extern | ||
|  |    private static function callPointer(ptr:cpp.Pointer<Vec>):Int; | ||
|  | 
 | ||
|  |    public function testPointerCast() { | ||
|  |       var map = new Map<Int, cpp.Pointer<Vec> >(); | ||
|  |       map.set(1,null); | ||
|  |       var result = callPointer( map.get(2) ); | ||
|  |       assertTrue(result==5); | ||
|  |    } | ||
|  | 
 | ||
|  |    public function testDynamic() { | ||
|  |       var a = [1]; | ||
|  |       var intPtr = a.address(0); | ||
|  |       var d:Dynamic = intPtr; | ||
|  |       assertFalse(d==[2].address(0)); | ||
|  |       assertTrue(d==a.address(0)); | ||
|  |       var anon = anonOf(d); | ||
|  |       assertFalse([2].address(0)==d); | ||
|  |       assertTrue(a.address(0)==d); | ||
|  |       assertFalse(intPtr==[2].address(0)); | ||
|  |       assertTrue(intPtr==a.address(0)); | ||
|  |       assertFalse(anon.ptr==[2].address(0)); | ||
|  |       assertTrue(anon.ptr==a.address(0)); | ||
|  |       assertFalse([2].address(0)==anon.ptr); | ||
|  |       assertTrue(a.address(0)==anon.ptr); | ||
|  |    } | ||
|  | 
 | ||
|  |    function getAnonI(a:Dynamic) : Dynamic | ||
|  |    { | ||
|  |       return a.i; | ||
|  |    } | ||
|  | 
 | ||
|  | 
 | ||
|  |    public function testAnon() { | ||
|  |       var a = [1]; | ||
|  |       var intPtr = a.address(0); | ||
|  |       var anon = { i:intPtr }; | ||
|  |       assertTrue( getAnonI(anon)==intPtr ); | ||
|  | 
 | ||
|  |       var vecPtr = VecStructAccess.create(1); | ||
|  |       var anon = { i:vecPtr }; | ||
|  |       assertTrue( getAnonI(anon)==vecPtr ); | ||
|  | 
 | ||
|  |       var vec:VecStruct = null; | ||
|  |       vec.x = 123; | ||
|  |       var anon = { i:vec }; | ||
|  |       assertTrue( getAnonI(anon)==vec ); | ||
|  |    } | ||
|  | 
 | ||
|  |    static function callMe(x:Int) return 10+x; | ||
|  | 
 | ||
|  |    static function notProcAddress(module:String, func:String) return null; | ||
|  | 
 | ||
|  |    public function testArrayAccess() { | ||
|  |        var array = [ 0.0, 1.1, 2.2, 3.3 ]; | ||
|  |        var ptr = cpp.Pointer.arrayElem(array, 0); | ||
|  |        assertTrue( ptr[1]==1.1 ); | ||
|  |        ptr[1] = 2; | ||
|  |        assertTrue( ptr[1]==2 ); | ||
|  |        ptr[1]++; | ||
|  |        assertTrue( ptr[1]==3 ); | ||
|  |        ptr[1]-=2.5; | ||
|  |        assertTrue( ptr[1]==0.5 ); | ||
|  | 
 | ||
|  |        var raw = ptr.raw; | ||
|  |        assertTrue( raw[2]==2.2 ); | ||
|  |        raw[2] = 2; | ||
|  |        assertTrue( raw[2]==2 ); | ||
|  |        raw[2]++; | ||
|  |        assertTrue( raw[2]==3 ); | ||
|  |        raw[2]-=2.5; | ||
|  |        assertTrue( raw[2]==0.5 ); | ||
|  | 
 | ||
|  |    } | ||
|  | 
 | ||
|  |    public function testFromRaw() | ||
|  |    { | ||
|  |       var i = new IntHolder(3); | ||
|  |       var ptr = cpp.Pointer.fromRaw(cpp.Pointer.addressOf(i).rawCast()); | ||
|  |       assertTrue( ptr.ref.ival==i.ival ); | ||
|  |       ptr.ref.ival==23; | ||
|  |       assertTrue( ptr.ref.ival==i.ival ); | ||
|  |    } | ||
|  | 
 | ||
|  |      private static var output:cpp.Pointer<Array<Int>>; | ||
|  | 
 | ||
|  |      private static var arrayValue:Array<Int>; | ||
|  |      private static function makeValue():{ a:cpp.Pointer<Array<Int>> } | ||
|  |      { | ||
|  |        arrayValue = [9]; | ||
|  |        return { a: cpp.Pointer.addressOf(arrayValue) }; | ||
|  |      } | ||
|  | 
 | ||
|  |      @:analyzer(no_fusion) | ||
|  |      public function testDynamicOutput() | ||
|  |      { | ||
|  |        // Declared as structure (just `var val = ...` works too) | ||
|  |        var val:{ a:cpp.Pointer<Array<Int>> } = makeValue(); | ||
|  | 
 | ||
|  |        var a:cpp.Pointer<Array<Int>> = val.a; | ||
|  |        output = a; | ||
|  |        output = (val.a:Dynamic); | ||
|  |        output = val.a; | ||
|  |        output = (val.a:cpp.Pointer<Array<Int>>); | ||
|  |        val.a = output; | ||
|  | 
 | ||
|  |        // Declared as Dynamic | ||
|  |        var val2:Dynamic = makeValue(); | ||
|  |        a = val2.a; | ||
|  |        output = a; | ||
|  |        output = (val2.a:Dynamic); | ||
|  |        output = val2.a; | ||
|  |        output = (val2.a:cpp.Pointer<Array<Int>>); | ||
|  |        val2.a = output; | ||
|  |        assertTrue( val2.a==output ); | ||
|  |        assertTrue( output==val.a ); | ||
|  |      } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  |    public function testAutoCast() { | ||
|  |        var z = [ 1, 2, 3 ]; | ||
|  |        assertTrue( cpp.NativeArray.address(z, 0).ptr == cpp.NativeArray.address(z, 0).ptr ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1).ptr != cpp.NativeArray.address(z, 0).ptr ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1).gt(cpp.NativeArray.address(z, 0)) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1).geq(cpp.NativeArray.address(z, 0)) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1).geq(cpp.NativeArray.address(z, 1)) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 0).leq(cpp.NativeArray.address(z, 0)) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1).leq(cpp.NativeArray.address(z, 2)) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1).leq(cpp.NativeArray.address(z, 2)) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 0) == cpp.Pointer.ofArray(z) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1) == cpp.Pointer.arrayElem(z,1) ); | ||
|  |        assertTrue( cpp.NativeArray.address(z, 1) != cpp.Pointer.fromHandle(null) ); | ||
|  |        assertTrue( cpp.Function.fromStaticFunction(callMe)(1)==11 ); | ||
|  |        try | ||
|  |        { | ||
|  |           assertTrue( cpp.Function.fromStaticFunction(notProcAddress)!=cpp.Function.getProcAddress("nomodule","nofunc!") ); | ||
|  |        } | ||
|  |        catch(e:Dynamic) | ||
|  |        { | ||
|  |          // Could not load module - expected | ||
|  |        } | ||
|  |    } | ||
|  | 
 | ||
|  |    static function functionCaller(fn:cpp.Function<Void->Int,cpp.abi.Abi>) { | ||
|  |         var a = fn.call(); | ||
|  |     } | ||
|  | 
 | ||
|  |    public function testFunctionStructAccess() { | ||
|  |        assertTrue( functionCaller != null ); | ||
|  |    } | ||
|  | 
 | ||
|  |    public function testSetData() { | ||
|  |       var ss:SomeStruct = null; | ||
|  |       ss.dataLength = 4; | ||
|  |       ss.data = cast "bye!".c_str(); | ||
|  |       var b = ss.getDataBytes(); | ||
|  |       assertTrue( b.getString(0, b.length) == "bye!" ); | ||
|  | 
 | ||
|  |       var ss:SomeStruct = null; | ||
|  |       var b = ss.getUnmanagedDataBytes(); | ||
|  |       assertTrue( b.getString(0, b.length) == "Hi!" ); | ||
|  |    } | ||
|  | 
 | ||
|  |    public function testZero() { | ||
|  |       var a = [1,2,3]; | ||
|  |       a.zero(); | ||
|  |       assertTrue(a.length==3); | ||
|  |       assertTrue(a[0]==0); | ||
|  |       assertTrue(a[1]==0); | ||
|  |       assertTrue(a[2]==0); | ||
|  |    } | ||
|  | 
 | ||
|  |    public function testMemcmp() { | ||
|  |       var a = [1,2,3]; | ||
|  |       var b = [2,2,3]; | ||
|  |       assertTrue( a.memcmp(b) == -1 ); | ||
|  |       assertTrue( b.memcmp(a) == 1 ); | ||
|  |       assertTrue( a.memcmp(a) == 0 ); | ||
|  |    } | ||
|  | 
 | ||
|  |    public function testCapacity() { | ||
|  |       var a = [1,2,3]; | ||
|  |       assertTrue( a.capacity() < 1000 ); | ||
|  |       a.reserve(1000); | ||
|  |       assertTrue( a.capacity() == 1000 ); | ||
|  |       a[1000] = 1; | ||
|  |       assertTrue( a.capacity() > 1000 ); | ||
|  |    } | ||
|  | 
 | ||
|  | 
 | ||
|  |    public function testElementSize() { | ||
|  |       var a = [1]; | ||
|  |       assertTrue( a.getElementSize() == cpp.Stdlib.sizeof(Int)  ); | ||
|  |       var a = ["hello!"]; | ||
|  |       assertTrue( a.getElementSize() == cpp.Stdlib.sizeof(String)  ); | ||
|  |       var a = [7.1]; | ||
|  |       assertTrue( a.getElementSize() == cpp.Stdlib.sizeof(Float)  ); | ||
|  |    } | ||
|  | 
 | ||
|  | 
 | ||
|  |    public function testBlit() { | ||
|  |       var a = [1,2,3,4]; | ||
|  |       var b = [0,0,0,0]; | ||
|  |       b.blit(0,a,0,a.length); | ||
|  |       for(i in 0...4) | ||
|  |         assertTrue(b[i] == a[i]); | ||
|  |       for(i in 0...4) | ||
|  |          b.blit(i,a,0,1); | ||
|  |       for(i in 0...4) | ||
|  |         assertTrue(b[i] == a[0]); | ||
|  |       for(i in 0...4) | ||
|  |          b.blit(i,a,2,1); | ||
|  |       for(i in 0...4) | ||
|  |         assertTrue(b[i] == a[2]); | ||
|  |    } | ||
|  | } | ||
|  | 
 |