diff --git a/src/Mono/Mono.hpp b/src/Mono/Mono.hpp index fc7a9bd..2824f1a 100644 --- a/src/Mono/Mono.hpp +++ b/src/Mono/Mono.hpp @@ -24,6 +24,8 @@ typedef f64 Double; typedef union { mono_bool wide_bool; } Bool; //USAGE: Bool t = {true}; typedef char16_t Char; typedef MonoString* String; +/// @warning MonoObject can be moved in memory by GC in any time and raw pointer will be invalid. +/// Use ObjectHandle where it is possible. typedef MonoObject* Object; typedef void Void; @@ -133,25 +135,39 @@ public: std::shared_ptr loadAssembly(const std::string& name); }; -class ObjectHandle { - Object object; +/// @brief ObjectHandle can be used to store reliable reference to MonoObject. +/// MonoObject can be moved in memory by GC in any time and raw pointer will be invalid. +struct ObjectHandle { u32 gc_handle; -public: - inline ObjectHandle() : object(nullptr), gc_handle(0) {} - inline ObjectHandle(Object obj) : object(obj) { gc_handle = mono_gchandle_new(obj, false); } + + inline ObjectHandle() : gc_handle(0) {} + + inline ObjectHandle(Object obj) { + gc_handle = mono_gchandle_new(obj, false); + } + + /// implicitly create new ObjectHandle instead inline ObjectHandle(const ObjectHandle& o) = delete; - inline ObjectHandle(ObjectHandle&& o) - : object(o.object), gc_handle(o.gc_handle) - { o.gc_handle = 0; }; + + inline ObjectHandle(ObjectHandle&& o) { + gc_handle = o.gc_handle; + o.gc_handle = 0; + } + inline ObjectHandle& operator=(ObjectHandle&& o) { - object = o.object; gc_handle = o.gc_handle; o.gc_handle = 0; return *this; - }; - inline ~ObjectHandle() { if(gc_handle) mono_gchandle_free(gc_handle); } - inline Object getObject() const { return object; } - inline u32 getGCHandle() const { return gc_handle; } + } + + inline ~ObjectHandle() { + if(gc_handle) + mono_gchandle_free(gc_handle); + } + + inline Object getObject() const { + return mono_gchandle_get_target(gc_handle); + } }; } diff --git a/src/main.cpp b/src/main.cpp index 91282c7..b10de9b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,7 +11,7 @@ using namespace ougge; -#define GAMEOBJECTPOOL_SIZE 64*1024 +#define GAMEOBJECTPOOL_SIZE 64 #define optime(N, LABEL, CODE) {\ nsec_t b = getMonotonicTimeNsec();\ @@ -43,21 +43,20 @@ int main(int argc, const char** argv){ auto a = mono.loadAssembly("Ougge.dll"); MonoClass* gameObjectClass = a->getClass("Ougge", "GameObject"); - MonoObject* exampleObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass); u64 obj_id = 0; - auto pair = p.emplace(GameObject(exampleObjectManaged)); + auto pair = p.emplace(GameObject(mono_object_new(mono.getDomain(), gameObjectClass))); + Mono::ObjectHandle& exampleObjectHandle = pair.second.getObjectHandle(); auto gameObjectCtor = Mono::Method(gameObjectClass, ".ctor"); - gameObjectCtor(exampleObjectManaged, obj_id++, pair.first); + gameObjectCtor(exampleObjectHandle.getObject(), obj_id++, pair.first); auto exampleObjectUpdate = Mono::Method(gameObjectClass, "InvokeUpdate"); - updateCallbacks.push_back([exampleObjectManaged, exampleObjectUpdate](f64 deltaTime) -> void { - exampleObjectUpdate(exampleObjectManaged, deltaTime); + updateCallbacks.push_back([&exampleObjectHandle, exampleObjectUpdate](f64 deltaTime) -> void { + exampleObjectUpdate(exampleObjectHandle.getObject(), deltaTime); }); auto tryCreateComponent = Mono::Method(gameObjectClass, "TryCreateComponent_internal"); Mono::String componentNameManaged = mono_string_new(mono.getDomain(), "Ougge.ExampleComponent"); - // Mono::ObjectHandle componentNameObjectHandle((MonoObject*)(void*)componentNameManaged); - Mono::Bool created = tryCreateComponent(exampleObjectManaged, componentNameManaged); + Mono::Bool created = tryCreateComponent(exampleObjectHandle.getObject(), componentNameManaged); if(!created.wide_bool) throw UsefulException("couldn't create ExampleComponent");