From 09326f5104bdf6290a9b3f071e69bf650347758e Mon Sep 17 00:00:00 2001 From: Ruslan Mustakov Date: Thu, 11 Jan 2018 16:52:41 +0700 Subject: [PATCH] Fix Reference leak and improve gdnew performance --- godot.nimble | 2 +- godot/godotapigen.nim | 3 ++- godot/nim/godotnim.nim | 24 +++++++++++++++++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/godot.nimble b/godot.nimble index b2d68a7..8415020 100644 --- a/godot.nimble +++ b/godot.nimble @@ -1,4 +1,4 @@ -version = "0.7.0" +version = "0.7.1" author = "Xored Software, Inc." description = "Godot Engine bindings" license = "MIT" diff --git a/godot/godotapigen.nim b/godot/godotapigen.nim index 6d7eae5..f8c06e3 100644 --- a/godot/godotapigen.nim +++ b/godot/godotapigen.nim @@ -612,7 +612,8 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string], elif isObjRet: body.add(newNode(nkAsgn).addChain(ident("result"), newCall(newBracketExpr(ident("asNimGodotObject"), - newCall("type", ident("result"))), retValIdent))) + newCall("type", ident("result"))), + retValIdent, ident("false"), ident("true")))) elif isStringRet: body.add(newNode(nkAsgn).addChain(ident("result"), newCall("$", retValIdent))) diff --git a/godot/nim/godotnim.nim b/godot/nim/godotnim.nim index 5a346c6..01da5ac 100644 --- a/godot/nim/godotnim.nim +++ b/godot/nim/godotnim.nim @@ -140,6 +140,13 @@ proc reference(o: ptr GodotObject): bool {.discardable.} = cstring"reference") referenceMethodBind.ptrCall(o, nil, addr result) +var initRefMethodBind {.threadvar.}: ptr GodotMethodBind +proc initRef(o: ptr GodotObject): bool {.discardable.} = + if isNil(initRefMethodBind): + initRefMethodBind = getMethod(cstring"Reference", + cstring"init_ref") + initRefMethodBind.ptrCall(o, nil, addr result) + proc deinit*(obj: NimGodotObject) = ## Destroy the object. You only need to call this for objects not inherited ## from Reference, where manual lifecycle control is necessary. @@ -240,7 +247,7 @@ proc newNimGodotObject[T: NimGodotObject]( result.godotObject.reference() proc asNimGodotObject*[T: NimGodotObject]( - godotObject: ptr GodotObject, forceNativeObject: bool = false): T = + godotObject: ptr GodotObject, forceNativeObject, noRef: bool = false): T = ## Wraps ``godotObject`` into Nim type ``T``. ## This is used by `godotapigen `_ and should rarely be ## used by anything else. @@ -253,7 +260,8 @@ proc asNimGodotObject*[T: NimGodotObject]( result = nil if result.isNil: result = newNimGodotObject[T]( - godotObject, cstring(godotObject.getClassName()), forceNativeObject) + godotObject, cstring(godotObject.getClassName()), + forceNativeObject or noRef) proc newVariant*(obj: NimGodotObject): Variant {.inline.} = newVariant(obj.godotObject) @@ -377,9 +385,15 @@ proc gdnew*[T: NimGodotObject](): T = ## Instantiates new object of type ``T``. const godotName = asCString(toGodotName(T)) const objInfo = classRegistryStatic[godotName] - result = when objInfo.isNative: - asNimGodotObject[T](getClassConstructor(godotName)()) - else: newOwnObj[T](godotName) + when objInfo.isNative: + let godotObject = getClassConstructor(godotName)() + new(result, nimGodotObjectFinalizer[T]) + result.godotObject = godotObject + when objInfo.isRef: + godotObject.initRef() + result.isRef = true + else: + result = newOwnObj[T](godotName) proc newCallError*(err: VariantCallError): ref CallError = ## Instantiates ``CallError`` from Godot ``err``.