Fix Reference leak and improve gdnew performance

This commit is contained in:
Ruslan Mustakov 2018-01-11 16:52:41 +07:00
commit 09326f5104
3 changed files with 22 additions and 7 deletions

View file

@ -1,4 +1,4 @@
version = "0.7.0" version = "0.7.1"
author = "Xored Software, Inc." author = "Xored Software, Inc."
description = "Godot Engine bindings" description = "Godot Engine bindings"
license = "MIT" license = "MIT"

View file

@ -612,7 +612,8 @@ proc doGenerateMethod(tree: PNode, methodBindRegistry: var HashSet[string],
elif isObjRet: elif isObjRet:
body.add(newNode(nkAsgn).addChain(ident("result"), body.add(newNode(nkAsgn).addChain(ident("result"),
newCall(newBracketExpr(ident("asNimGodotObject"), newCall(newBracketExpr(ident("asNimGodotObject"),
newCall("type", ident("result"))), retValIdent))) newCall("type", ident("result"))),
retValIdent, ident("false"), ident("true"))))
elif isStringRet: elif isStringRet:
body.add(newNode(nkAsgn).addChain(ident("result"), body.add(newNode(nkAsgn).addChain(ident("result"),
newCall("$", retValIdent))) newCall("$", retValIdent)))

View file

@ -140,6 +140,13 @@ proc reference(o: ptr GodotObject): bool {.discardable.} =
cstring"reference") cstring"reference")
referenceMethodBind.ptrCall(o, nil, addr result) 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) = proc deinit*(obj: NimGodotObject) =
## Destroy the object. You only need to call this for objects not inherited ## Destroy the object. You only need to call this for objects not inherited
## from Reference, where manual lifecycle control is necessary. ## from Reference, where manual lifecycle control is necessary.
@ -240,7 +247,7 @@ proc newNimGodotObject[T: NimGodotObject](
result.godotObject.reference() result.godotObject.reference()
proc asNimGodotObject*[T: NimGodotObject]( 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``. ## Wraps ``godotObject`` into Nim type ``T``.
## This is used by `godotapigen <godotapigen.html>`_ and should rarely be ## This is used by `godotapigen <godotapigen.html>`_ and should rarely be
## used by anything else. ## used by anything else.
@ -253,7 +260,8 @@ proc asNimGodotObject*[T: NimGodotObject](
result = nil result = nil
if result.isNil: if result.isNil:
result = newNimGodotObject[T]( result = newNimGodotObject[T](
godotObject, cstring(godotObject.getClassName()), forceNativeObject) godotObject, cstring(godotObject.getClassName()),
forceNativeObject or noRef)
proc newVariant*(obj: NimGodotObject): Variant {.inline.} = proc newVariant*(obj: NimGodotObject): Variant {.inline.} =
newVariant(obj.godotObject) newVariant(obj.godotObject)
@ -377,9 +385,15 @@ proc gdnew*[T: NimGodotObject](): T =
## Instantiates new object of type ``T``. ## Instantiates new object of type ``T``.
const godotName = asCString(toGodotName(T)) const godotName = asCString(toGodotName(T))
const objInfo = classRegistryStatic[godotName] const objInfo = classRegistryStatic[godotName]
result = when objInfo.isNative: when objInfo.isNative:
asNimGodotObject[T](getClassConstructor(godotName)()) let godotObject = getClassConstructor(godotName)()
else: newOwnObj[T](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 = proc newCallError*(err: VariantCallError): ref CallError =
## Instantiates ``CallError`` from Godot ``err``. ## Instantiates ``CallError`` from Godot ``err``.