Proper handling of References
This commit is contained in:
parent
b023775f79
commit
863df0ae45
2 changed files with 51 additions and 12 deletions
|
|
@ -264,16 +264,29 @@ proc rangeError(nimType: cstring, value: string, className: cstring,
|
|||
|
||||
proc nimDestroyFunc(obj: ptr GodotObject, methData: pointer,
|
||||
userData: pointer) {.noconv.} =
|
||||
let nimObj = cast[ref NimGodotObject](userData)
|
||||
let nimObj = cast[NimGodotObject](userData)
|
||||
nimObj.removeGodotObject()
|
||||
GC_unref(nimObj)
|
||||
|
||||
template registerGodotClass(classNameIdent, classNameLit,
|
||||
proc nimDestroyRefFunc(obj: ptr GodotObject, methData: pointer,
|
||||
userData: pointer) {.noconv.} =
|
||||
# references are destroyed by Godot when they are already destroyed by Nim,
|
||||
# so nothing to do here.
|
||||
discard
|
||||
|
||||
proc refcountIncremented*(obj: NimGodotObject) =
|
||||
GC_ref(obj)
|
||||
|
||||
proc refcountDecremented*(obj: NimGodotObject): bool =
|
||||
GC_unref(obj)
|
||||
|
||||
template registerGodotClass(classNameIdent, classNameLit, isRef,
|
||||
baseNameLit, createFuncIdent) =
|
||||
proc createFuncIdent(obj: ptr GodotObject,
|
||||
methData: pointer): pointer {.noconv.} =
|
||||
let nimObj = new(classNameIdent)
|
||||
setGodotObject(nimObj, obj)
|
||||
nimObj.setOwn()
|
||||
nimObj.setGodotObject(obj)
|
||||
GC_ref(nimObj)
|
||||
result = cast[pointer](nimObj)
|
||||
|
||||
|
|
@ -281,7 +294,7 @@ template registerGodotClass(classNameIdent, classNameLit,
|
|||
createFunc: createFuncIdent
|
||||
)
|
||||
let destroyFuncObj = GodotInstanceDestroyFunc(
|
||||
destroyFunc: nimDestroyFunc
|
||||
destroyFunc: when isRef: nimDestroyRefFunc else: nimDestroyFunc
|
||||
)
|
||||
registerClass(classNameIdent, classNameLit, false)
|
||||
godotScriptRegisterClass(getNativeLibHandle(), classNameLit, baseNameLit,
|
||||
|
|
@ -328,7 +341,7 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
|
|||
godotScriptRegisterProperty(getNativeLibHandle(), classNameLit, propNameLit,
|
||||
attr, setFunc, getFunc)
|
||||
static:
|
||||
import strutils
|
||||
import strutils, sets
|
||||
proc toGodotStyle(s: string): string {.compileTime.} =
|
||||
result = newStringOfCap(s.len + 10)
|
||||
for c in s:
|
||||
|
|
@ -385,12 +398,14 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
|||
result.add(meth.nimNode)
|
||||
|
||||
# 4. Register Godot object
|
||||
let parentName = if obj.parentName.isNil: newNilLit()
|
||||
let parentName = if obj.parentName.isNil: newStrLitNode("Object")
|
||||
else: newStrLitNode(obj.parentName)
|
||||
let classNameLit = newCStringLit(obj.name)
|
||||
let classNameIdent = ident(obj.name)
|
||||
let isRef: bool = if obj.parentName.isNil: false
|
||||
else: obj.parentName in refClasses
|
||||
result.add(getAst(
|
||||
registerGodotClass(classNameIdent, classNameLit, parentName,
|
||||
registerGodotClass(classNameIdent, classNameLit, isRef, parentName,
|
||||
genSym(nskProc, "createFunc"))))
|
||||
|
||||
# 5. Register fields (properties)
|
||||
|
|
@ -467,6 +482,20 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
|||
argTypes, genSym(nskProc, "methFunc"),
|
||||
hasReturnValue)))
|
||||
|
||||
if isRef:
|
||||
# add ref/unref for types inherited from Reference
|
||||
let noArgs = newSeq[NimNode]()
|
||||
result.add(getAst(
|
||||
registerGodotMethod(classNameLit, classNameIdent, ident("refcountIncremented"),
|
||||
cstring"_refcount_incremented", 0, 0,
|
||||
noArgs, genSym(nskProc, "refcount_incremented"),
|
||||
ident("false"))))
|
||||
result.add(getAst(
|
||||
registerGodotMethod(classNameLit, classNameIdent, ident("refcountDecremented"),
|
||||
cstring"_refcount_decremented", 0, 0,
|
||||
noArgs, genSym(nskProc, "refcount_decremented"),
|
||||
ident("true"))))
|
||||
|
||||
macro gdobj*(definition: untyped, body: untyped): typed =
|
||||
let typeDef = parseType(definition, callsite())
|
||||
result = genType(typeDef)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import "../core/strings.nim", "../core/vector2.nim", "../core/rect2.nim",
|
|||
type
|
||||
NimGodotObject* = ref object of RootObj
|
||||
godotObject: ptr GodotObject
|
||||
isRef: bool
|
||||
isExternalRef: bool
|
||||
isOwn: bool
|
||||
|
||||
ConversionResult* {.pure.} = enum
|
||||
OK,
|
||||
|
|
@ -51,7 +52,8 @@ var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo]
|
|||
|
||||
static:
|
||||
import sets, strutils
|
||||
var nativeClasses {.compileTime.} = initSet[string]()
|
||||
var nativeClasses {.compileTime.} = newSeq[string]()
|
||||
var refClasses* {.compileTime.} = newSeq[string]()
|
||||
|
||||
var getClassMethodBind {.threadvar.}: ptr GodotMethodBind
|
||||
proc getClassName*(o: ptr GodotObject): string =
|
||||
|
|
@ -87,7 +89,9 @@ proc deinit*(obj: NimGodotObject) =
|
|||
|
||||
proc godotFinalizer[T: NimGodotObject](obj: T) =
|
||||
if obj.godotObject.isNil: return
|
||||
if obj.isRef and obj.godotObject.unreference():
|
||||
if obj.isExternalRef and obj.godotObject.unreference():
|
||||
obj.deinit()
|
||||
elif obj.isOwn:
|
||||
obj.deinit()
|
||||
|
||||
macro baseNativeType(T: typedesc): cstring =
|
||||
|
|
@ -139,9 +143,12 @@ template registerClass*(T: typedesc; godotClassName: cstring,
|
|||
isNative: isNativeParam,
|
||||
isRef: isRef
|
||||
)
|
||||
when isRef:
|
||||
static:
|
||||
refClasses.add(T.name)
|
||||
when isNativeParam:
|
||||
static:
|
||||
nativeClasses.incl(T.name)
|
||||
nativeClasses.add(T.name)
|
||||
|
||||
proc newNimGodotObject[T: NimGodotObject](
|
||||
godotObject: ptr GodotObject, godotClassName: cstring): T =
|
||||
|
|
@ -154,7 +161,7 @@ proc newNimGodotObject[T: NimGodotObject](
|
|||
result = T(objInfo.constructor())
|
||||
result.godotObject = godotObject
|
||||
if objInfo.isRef:
|
||||
result.isRef = true
|
||||
result.isExternalRef = true
|
||||
result.godotObject.reference()
|
||||
|
||||
proc asNimGodotObject*[T: NimGodotObject](godotObject: ptr GodotObject): T =
|
||||
|
|
@ -252,6 +259,9 @@ proc setGodotObject*(nimObj: NimGodotObject, obj: ptr GodotObject) {.inline.} =
|
|||
assert(nimObj.godotObject.isNil) # reassignment is not allowed
|
||||
nimObj.godotObject = obj
|
||||
|
||||
proc setOwn*(nimObj: NimGodotObject) {.inline.} =
|
||||
nimObj.isOwn = true
|
||||
|
||||
proc godotObject*(nimObj: NimGodotObject): ptr GodotObject {.inline.} =
|
||||
nimObj.godotObject
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue