Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,4 @@
-cp src
-main TestMain
-neko bin/neko/TestMain.n
-cp ../unit

View File

@ -0,0 +1,5 @@
-cp src
-main TestMain
-cpp bin/cpp-utf8
-cp ../unit
-D disable_unicode_strings

View File

@ -0,0 +1,4 @@
-cp src
-main TestMain
-cpp bin/cpp
-cp ../unit

View File

@ -0,0 +1,381 @@
#ifndef STATIC_LINK
#define IMPLEMENT_API
#endif
#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX)
// Include neko glue....
#define NEKO_COMPATIBLE
#endif
#include <hx/CFFIPrime.h>
#include <math.h>
#include <vector>
#include <string>
int addInts(int a, int b)
{
return a+b;
}
DEFINE_PRIME2(addInts);
void printString(const char *inMessage)
{
printf("Message : %s.\n", inMessage);
}
DEFINE_PRIME1v(printString);
std::vector<AutoGCRoot *> roots;
void setRoot(int inRoot, value inValue)
{
if (roots.size()<=inRoot)
roots.resize(inRoot+1);
if (roots[inRoot]==0)
roots[inRoot] = new AutoGCRoot(inValue);
else
roots[inRoot]->set(inValue);
}
DEFINE_PRIME2v(setRoot);
value getRoot(int inRoot)
{
if (inRoot>=roots.size() || !roots[inRoot])
return alloc_null();
return roots[inRoot]->get();
}
DEFINE_PRIME1(getRoot);
void clearRoots()
{
for(int i=0;i<roots.size();i++)
{
delete roots[i];
roots[i] = 0;
}
}
DEFINE_PRIME0v(clearRoots);
double distance3D(int x, int y, int z)
{
return sqrt( (double)(x*x + y*y+ z*z) );
}
DEFINE_PRIME3(distance3D);
void fields(value object)
{
if ( val_is_null(object))
printf("null fields\n");
else
printf("x : %f\n", val_field_numeric(object, val_id("x")) );
}
DEFINE_PRIME1v(fields);
HxString stringVal(HxString inString)
{
printf("String : %s (%d)\n", inString.c_str(), inString.size());
return HxString("Ok");
}
DEFINE_PRIME1(stringVal);
HxString getNullString()
{
return 0;
}
DEFINE_PRIME0(getNullString);
// Conflict with name - use anon-namespace
namespace {
value select(int which, value object0, value object1, value object2, value object3)
{
switch(which)
{
case 0: return object0;
case 1: return object1;
case 2: return object2;
case 3: return object3;
default: return alloc_null();
}
}
DEFINE_PRIME5(select);
}
float floats(bool add, float firstVal, float secondVal)
{
return add ? firstVal + secondVal : firstVal - secondVal;
}
DEFINE_PRIME3(floats);
int multi5(int i0, int i1, int i2, int i3, int i4)
{
return i0 + i1 + i2 + i3 + i4;
}
DEFINE_PRIME5(multi5);
int multi6(int i0, int i1, int i2, int i3, int i4, int i5)
{
return i0 + i1 + i2 + i3 + i4 + i5;
}
DEFINE_PRIME6(multi6);
int multi7(int i0, int i1, int i2, int i3, int i4, int i5, int i6)
{
return i0 + i1 + i2 + i3 + i4 + i5 + i6;
}
DEFINE_PRIME7(multi7);
int multi8(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7)
{
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7;
}
DEFINE_PRIME8(multi8);
int multi9(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8)
{
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8;
}
DEFINE_PRIME9(multi9);
int multi10(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9)
{
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9;
}
DEFINE_PRIME10(multi10);
int multi11(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10)
{
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10;
}
DEFINE_PRIME11(multi11);
int multi12(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11)
{
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11;
}
DEFINE_PRIME12(multi12);
HxString addStrings(HxString s0, HxString s1)
{
if (hxs_encoding(s0)!=hx::StringUtf16 && hxs_encoding(s1)!=hx::StringUtf16)
{
std::string w0 = hxs_utf8(s0,0);
std::string w1 = hxs_utf8(s1,0);
std::string result = w0+w1;
return alloc_hxs_utf8( result.c_str(), result.size() );
}
std::wstring w0 = hxs_wchar(s0,0);
std::wstring w1 = hxs_wchar(s1,0);
std::wstring result = w0+w1;
return alloc_hxs_wchar( result.c_str(), result.size() );
}
DEFINE_PRIME2(addStrings);
// Old-style CFFI
value isBool(value inVal)
{
return alloc_bool( val_is_bool(inVal) );
}
DEFINE_PRIM(isBool,1);
value isNull(value inVal)
{
return alloc_bool( val_is_null(inVal) );
}
DEFINE_PRIM(isNull,1);
value allocNull()
{
return alloc_null();
}
DEFINE_PRIM(allocNull,0);
value appendString(value bufVal, value stringVal)
{
buffer buf = val_to_buffer(bufVal);
val_buffer(buf,stringVal);
return buffer_val(buf);
}
DEFINE_PRIM(appendString,2);
value bufferToString(value bufVal)
{
buffer buf = val_to_buffer(bufVal);
return buffer_to_string(buf);
}
DEFINE_PRIM(bufferToString, 1);
value valToString(value a, value b)
{
buffer buf = alloc_buffer("String:");
val_buffer(buf,a);
val_buffer(buf,b);
return buffer_to_string(buf);
}
DEFINE_PRIM(valToString, 2);
value valIsBuffer(value bufVal)
{
return alloc_bool( val_is_buffer(bufVal) );
}
DEFINE_PRIM(valIsBuffer, 1);
value subBuffer(value inString, value inLen)
{
buffer buf = alloc_buffer("Cold as ");
const char *string = val_string(inString);
buffer_append_sub(buf,string, val_int(inLen) );
return buffer_to_string(buf);
}
DEFINE_PRIM(subBuffer, 2);
value charString(value inC0, value inC1, value inC2)
{
buffer buf = alloc_buffer("A ");
buffer_append_char(buf,val_int(inC0));
buffer_append_char(buf,val_int(inC1));
buffer_append_char(buf,val_int(inC2));
return buffer_to_string(buf);
}
DEFINE_PRIM(charString, 3);
value byteDataSize(value byteData)
{
CffiBytes bytes = getByteData(byteData);
if (bytes.data==0)
return alloc_null();
return alloc_int(bytes.length);
}
DEFINE_PRIM(byteDataSize, 1);
value byteDataByte(value byteData, value inIndex)
{
CffiBytes bytes = getByteData(byteData);
if (bytes.data==0)
return alloc_null();
return alloc_int(bytes.data[ val_int(inIndex) ]);
}
DEFINE_PRIM(byteDataByte, 2);
int myFreeCount = 0;
DEFINE_KIND(myKind);
void destroyMyKind(value inAbstract)
{
//printf("destroyMyKind\n");
// In this case, the data belongs to the abstract
myFreeCount++;
}
void freeMyKind(value inAbstract)
{
//printf("freeMyKind\n");
void *data = val_to_kind(inAbstract,myKind);
// In this case, we own the data, so must delete it
delete (int *)data;
myFreeCount++;
}
value allocAbstract()
{
if (!myKind)
myKind = alloc_kind();
void *data = new int(99);
value abs = alloc_abstract(myKind, data);
val_gc(abs, freeMyKind);
return abs;
}
DEFINE_PRIM(allocAbstract, 0);
value createAbstract()
{
if (!myKind)
myKind = alloc_kind();
value abs = create_abstract(myKind, sizeof(int), destroyMyKind);
int *data = (int *)val_get_handle(abs,myKind);
*data = 99;
return abs;
}
DEFINE_PRIM(createAbstract, 0);
value getAbstract(value inAbstract)
{
void *data = val_to_kind(inAbstract,myKind);
if (!data)
return alloc_int(-1);
return alloc_int(*(int *)data);
}
DEFINE_PRIM(getAbstract, 1);
value getAbstractFreeCount()
{
return alloc_int(myFreeCount);
}
DEFINE_PRIM(getAbstractFreeCount, 0);
value freeAbstract(value inAbstract)
{
free_abstract(inAbstract);
return alloc_null();
}
DEFINE_PRIM(freeAbstract, 1);
value createAnon()
{
value v = alloc_empty_object();
alloc_field(v,val_id("TInt"),alloc_int(7));
alloc_field(v,val_id("TFloat"),alloc_float(7.2));
alloc_field(v,val_id("TBool"),alloc_bool(true));
buffer buf = alloc_buffer_len(4);
int data = 0xdeadbeef;
memcpy(buffer_data(buf),&data,sizeof(int));
alloc_field(v,val_id("TClass(Array)"),buffer_val(buf));
return v;
}
DEFINE_PRIM(createAnon,0);

View File

@ -0,0 +1,15 @@
<xml>
<include name="${HXCPP}/toolchain/haxe-target.xml"/>
<files id="prime">
<depend files="hxcpp-depends"/>
<file name="Project.cpp" />
</files>
<target id="default" output="${LIBPREFIX}prime${HX_TARGET_SUFFIX}" tool="linker" toolid="${STD_MODULE_LINK}">
<outdir name="${NDLLDIR}/${BINDIR}" />
<files id="prime"/>
</target>
</xml>

View File

@ -0,0 +1,20 @@
#if macro
import haxe.macro.Expr;
#end
class Loader
{
#if cpp
public static function __init__()
{
cpp.Lib.pushDllSearchPath( "project/ndll/" + cpp.Lib.getBinDirectory() );
}
#end
public static inline macro function load(inName2:Expr, inSig:Expr)
{
return macro cpp.Prime.load("prime", $inName2, $inSig, false);
}
}

View File

@ -0,0 +1,18 @@
import haxe.PosInfos;
class TestBase extends haxe.unit.TestCase
{
public function assertClose(inWant:Float, inGot:Float, ?c : PosInfos )
{
assertTrue( Math.abs(inWant-inGot) < 0.001, c );
}
public function assertEq<T>(inWant:T, inGot:T, ?c : PosInfos )
{
var same = inWant==inGot;
if (!same)
trace('Expected $inWant, got $inGot');
assertTrue(same, c);
}
}

View File

@ -0,0 +1,193 @@
#if cpp
import cpp.Lib;
import cpp.vm.Gc;
#elseif neko
import neko.Lib;
import neko.vm.Gc;
#end
import Loader;
import haxe.io.BytesData;
class TestCffi extends TestBase
{
static var isBool:Dynamic->Bool = Lib.load("prime", "isBool", 1);
static var isNull:Dynamic->Bool = Lib.load("prime", "isNull", 1);
static var allocNull:Void->Dynamic = Lib.load("prime", "allocNull", 0);
static var appendString:BytesData->String->BytesData = Lib.load("prime", "appendString", 2);
static var bufferToString:BytesData->String = Lib.load("prime", "bufferToString", 1);
static var valIsBuffer:Dynamic->Bool = Lib.load("prime", "valIsBuffer", 1);
static var valToString:Dynamic->Dynamic->String = Lib.load("prime", "valToString", 2);
static var subBuffer:String->Int->String = Lib.load("prime", "subBuffer", 2);
static var charString:Int->Int->Int->String = Lib.load("prime", "charString", 3);
static var byteDataSize:haxe.io.Bytes->Int = Lib.load("prime", "byteDataSize", 1);
static var byteDataByte:haxe.io.Bytes->Int->Int = Lib.load("prime", "byteDataByte", 2);
static var setRoot:Int->Dynamic->Void = Lib.load("prime", "setRoot", 2);
static var getRoot:Int->Dynamic = Lib.load("prime", "getRoot", 1);
static var clearRoots:Void->Void = Lib.load("prime", "clearRoots", 0);
static var createAbstract:Void->Dynamic = Lib.load("prime", "createAbstract", 0);
static var allocAbstract:Void->Dynamic = Lib.load("prime", "allocAbstract", 0);
static var getAbstract:Dynamic->Int = Lib.load("prime", "getAbstract", 1);
static var freeAbstract:Dynamic->Void = Lib.load("prime", "freeAbstract", 1);
static var getAbstractFreeCount:Void->Int = Lib.load("prime", "getAbstractFreeCount", 0);
static var createAnon:Void->Dynamic = Lib.load("prime", "createAnon", 0);
static var cppObjectAsDynamic:cpp.Callable<Int->cpp.Object>;
inline function getObjectAsString() : String
{
// Just test to see if this compiles
if (cppObjectAsDynamic!=null)
return cppObjectAsDynamic(1);
return null;
}
public function testCffi()
{
cpp.Prime.nekoInit("prime");
assertTrue( isBool!=null );
assertTrue( isBool(true) );
assertTrue( isBool(false) );
assertFalse( isBool(21) );
assertFalse( isBool("Hello") );
assertFalse( isBool(null) );
assertTrue( isNull!=null );
assertTrue( isNull(null) );
assertFalse( isNull(false) );
assertFalse( isNull(32) );
assertFalse( isNull("") );
assertTrue( allocNull!=null );
assertEquals(null, allocNull() );
assertTrue( appendString!=null );
assertTrue( bufferToString!=null );
assertTrue( getRoot!=null );
assertTrue( setRoot!=null );
assertTrue( createAnon!=null );
assertFalse( valIsBuffer(null) );
assertFalse( valIsBuffer(1) );
assertFalse( valIsBuffer({}) );
assertFalse( valIsBuffer("String Buf") );
if (cppObjectAsDynamic!=null)
assertTrue( getObjectAsString()==null);
var anon = createAnon();
for(f in Reflect.fields(anon))
{
#if cpp
var value:Dynamic = Reflect.field(anon, f);
//trace(f + " " + Type.typeof(value) );
assertTrue( Std.string(Type.typeof(value)) == f );
#end
}
for(i in 0...100)
setRoot(i,[i]);
Gc.run(true);
var base = "Hello ";
var bytes = haxe.io.Bytes.ofString(base).getData();
#if !neko
assertTrue( valIsBuffer(bytes) );
// Can't acess neko buffer from haxe code
bytes = appendString(bytes,"World");
var result = bufferToString(bytes);
assertEq(result,"Hello World");
#end
assertEq(valToString(null,1),"String:null1");
assertEq(valToString("x",1.1),"String:x1.1");
assertEq(valToString("Hello"," World"),"String:Hello World");
assertEq(valToString([1],[]),"String:[1][]");
assertEq(subBuffer("hello",4),"Cold as hell");
#if !neko
assertEq(charString(99,97,116),"A cat");
#end
var bytes = haxe.io.Bytes.ofString("String Buffer");
assertEq( byteDataSize(bytes), 13 );
assertEq( byteDataByte(bytes,1), 't'.code );
assertEq( getAbstractFreeCount(), 0 );
var createdAbs = createAbstract();
assertTrue( createdAbs!=null );
assertEq( getAbstract(createdAbs), 99 );
// Explicitly freeing abstract does not call finalizer
freeAbstract( createdAbs );
assertEq( getAbstractFreeCount(), 0 );
assertEq( getAbstract(createdAbs), -1 );
assertEq( getAbstractFreeCount(), 0 );
createdAbs = null;
Gc.run(true);
assertEq( getAbstractFreeCount(), 0 );
var allocatedAbs = allocAbstract();
assertTrue( allocatedAbs!=null );
assertEq( getAbstract(allocatedAbs), 99 );
assertEq( getAbstractFreeCount(), 0 );
freeAbstract( allocatedAbs );
assertEq( getAbstract(allocatedAbs), -1 );
assertEq( getAbstractFreeCount(), 0 );
allocatedAbs = null;
createDeepAbstracts(2);
clearStack(12);
Gc.run(true);
var freeCount = getAbstractFreeCount();
if (freeCount!=2)
{
Sys.println('\nWarning: $freeCount != 2');
}
for(i in 0...100)
assertEq( getRoot(i)+"", [i]+"" );
clearRoots();
for(i in 0...100)
assertEq( getRoot(i), null );
assertEq( getAbstractFreeCount(), 2 );
}
function clearStack(count:Int, ?nothing:Dynamic):Dynamic
{
if (count==0)
return 0;
return clearStack(count-1);
}
// Try to hide references from GC stack marking
function createDeepAbstracts(inDepth:Int)
{
if (inDepth==0)
{
createAbstract();
allocAbstract();
}
else
createDeepAbstracts(inDepth-1);
}
}

View File

@ -0,0 +1,17 @@
class TestMain
{
public static function main()
{
var r = new haxe.unit.TestRunner();
r.add(new TestCffi());
r.add(new TestPrime());
var t0 = haxe.Timer.stamp();
var success = r.run();
trace(" Time : " + (haxe.Timer.stamp()-t0)*1000 );
Sys.exit(success ? 0 : 1);
}
}

View File

@ -0,0 +1,78 @@
class TestPrime extends TestBase
{
static var add = Loader.load("addInts", "iii" );
#if cpp
static var printString = Loader.load("printString", "cv" );
#end
static var distance3d = Loader.load("distance3D", "iiid" );
static var select = Loader.load("select", "iooooo" );
static var floats = Loader.load("floats", "bfff" );
static var stringVal = Loader.load("stringVal", "ss" );
static var multi5 = Loader.load("multi5", "iiiiii" );
static var multi6 = Loader.load("multi6", "iiiiiii" );
static var multi7 = Loader.load("multi7", "iiiiiiii" );
static var multi8 = Loader.load("multi8", "iiiiiiiii" );
static var multi9 = Loader.load("multi9", "iiiiiiiiii" );
static var multi10 = Loader.load("multi10","iiiiiiiiiii" );
static var multi11 = Loader.load("multi11","iiiiiiiiiiii" );
static var multi12 = Loader.load("multi12","iiiiiiiiiiiii" );
static var getNullString = Loader.load("getNullString","s" );
static var addStrings = Loader.load("addStrings", 'sss');
// Non-static test
var fields = Loader.load("fields", "ov" );
public function testPrime()
{
cpp.Prime.nekoInit("prime");
assertTrue(add!=null);
assertEquals(7, add(2,5));
#if cpp
printString("Hello World");
#end
var len = distance3d(3,4,5);
assertClose(50,len*len);
fields( { x:11, name:"Hello" } );
fields( null );
assertEquals("Ok", stringVal("HxString"));
assertEquals(null, getNullString());
assertEquals( ""+[1], ""+select(0, [1], "Hello", {x:1}, add) );
var shouldBeNull:String = "" + select(0, null, "Hello", {x:1}, add);
trace( "null ?" + shouldBeNull + "/" + shouldBeNull.length );
assertEquals( "null", shouldBeNull );
//assertEquals( "null", ""+select(0, null, "Hello", {x:1}, add) );
assertEquals( ""+"Hello", ""+select(1, [1], "Hello", {x:1}, add));
assertEquals( ""+{x:1}, ""+select(2, [1], "Hello", {x:1}, add) );
assertEquals( ""+add, ""+select(3, [1], "Hello", {x:1}, add) );
assertClose( 7.3, floats(true,4.2,3.1) );
assertClose( 1.1, floats(false,4.2,3.1) );
assertEquals( 5, multi5(1,1,1,1,1) );
assertEquals( 6, multi6(1,1,1,1,1,1) );
assertEquals( 7, multi7(1,1,1,1,1,1,1) );
assertEquals( 8, multi8(1,1,1,1,1,1,1,1) );
assertEquals( 9, multi9(1,1,1,1,1,1,1,1,1) );
assertEquals( 10, multi10(1,1,1,1,1,1,1,1,1,1) );
assertEquals( 11, multi11(1,1,1,1,1,1,1,1,1,1,1) );
assertEquals( 12, multi12(1,1,1,1,1,1,1,1,1,1,1,1) );
var s0 = "hello";
var s1 = "";
assertTrue( addStrings(s0,s0) == s0+s0 );
var s01 = addStrings(s0,s1);
assertTrue( s01 == s0+s1 );
var s11 = addStrings(s1,s1);
assertTrue( s11 == s1+s1 );
}
}