diff --git a/include/cpp/marshal/Definitions.inc b/include/cpp/marshal/Definitions.inc index bde43e655..ffd5f14b2 100644 --- a/include/cpp/marshal/Definitions.inc +++ b/include/cpp/marshal/Definitions.inc @@ -213,6 +213,21 @@ namespace cpp T& operator[] (int64_t index) const; }; + class RootHandle + { + ::hx::Object** object; + + RootHandle(hx::Object** obj); + + public: + static RootHandle create(Dynamic obj); + static RootHandle fromVoidPointer(::cpp::Pointer ptr); + + ::cpp::Pointer toVoidPointer(); + Dynamic getObject(); + void close(); + }; + struct Marshal final { #ifdef HXCPP_BIG_ENDIAN diff --git a/include/cpp/marshal/RootHandle.hpp b/include/cpp/marshal/RootHandle.hpp new file mode 100644 index 000000000..fcdeb83e2 --- /dev/null +++ b/include/cpp/marshal/RootHandle.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "Definitions.inc" + +inline cpp::marshal::RootHandle::RootHandle(::hx::Object** obj) : object(obj) {} + +inline cpp::marshal::RootHandle cpp::marshal::RootHandle::create(::Dynamic obj) +{ + if (null() == obj) + { + hx::NullReference("Dynamic", false); + } + + auto root = new hx::Object* { obj.mPtr }; + + hx::GCAddRoot(root); + + return RootHandle(root); +} + +inline cpp::marshal::RootHandle cpp::marshal::RootHandle::fromVoidPointer(cpp::Pointer ptr) +{ + if (nullptr == ptr.ptr) + { + hx::NullReference("Dynamic", false); + } + + return RootHandle(static_cast(ptr.ptr)); +} + +inline void cpp::marshal::RootHandle::close() +{ + hx::GCRemoveRoot(object); + + delete object; +} + +inline ::Dynamic cpp::marshal::RootHandle::getObject() +{ + return ::Dynamic{ *object }; +} + +inline cpp::Pointer cpp::marshal::RootHandle::toVoidPointer() +{ + return object; +} \ No newline at end of file diff --git a/include/hxcpp.h b/include/hxcpp.h index 71618c1b3..c9680242d 100755 --- a/include/hxcpp.h +++ b/include/hxcpp.h @@ -358,6 +358,7 @@ typedef PropertyAccessMode PropertyAccess; #include #include #include +#include #include #include #include diff --git a/test/native/Native.hx b/test/native/Native.hx index d82f41a19..5b300a23b 100644 --- a/test/native/Native.hx +++ b/test/native/Native.hx @@ -47,6 +47,8 @@ class Native new tests.marshalling.view.TestMarshal(), new tests.marshalling.view.TestViewExtensions(), + new tests.marshalling.root.TestRoot(), + new tests.encoding.TestAscii(), new tests.encoding.TestUtf8(), new tests.encoding.TestUtf16(), diff --git a/test/native/tests/marshalling/root/TestRoot.hx b/test/native/tests/marshalling/root/TestRoot.hx new file mode 100644 index 000000000..509fa8e0e --- /dev/null +++ b/test/native/tests/marshalling/root/TestRoot.hx @@ -0,0 +1,34 @@ +package tests.marshalling.root; + +import cpp.marshal.RootHandle; +import utest.Assert; +import utest.Test; + +class TestRoot extends Test { + function test_null_object() { + Assert.raises(() -> RootHandle.create(null)); + } + + function test_null_void_pointer() { + Assert.raises(() -> RootHandle.fromVoidPointer(null)); + } + + function test_get_object() { + final obj = "Hello, World!"; + final handle = RootHandle.create(obj); + + Assert.equals(obj, handle.getObject()); + + handle.close(); + } + + function test_void_pointer_roundtrip() { + final obj = "Hello, World!"; + final ptr = RootHandle.create(obj).toVoidPointer(); + final handle = RootHandle.fromVoidPointer(ptr); + + Assert.equals(obj, handle.getObject()); + + handle.close(); + } +} \ No newline at end of file