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,
|
proc nimDestroyFunc(obj: ptr GodotObject, methData: pointer,
|
||||||
userData: pointer) {.noconv.} =
|
userData: pointer) {.noconv.} =
|
||||||
let nimObj = cast[ref NimGodotObject](userData)
|
let nimObj = cast[NimGodotObject](userData)
|
||||||
nimObj.removeGodotObject()
|
nimObj.removeGodotObject()
|
||||||
GC_unref(nimObj)
|
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) =
|
baseNameLit, createFuncIdent) =
|
||||||
proc createFuncIdent(obj: ptr GodotObject,
|
proc createFuncIdent(obj: ptr GodotObject,
|
||||||
methData: pointer): pointer {.noconv.} =
|
methData: pointer): pointer {.noconv.} =
|
||||||
let nimObj = new(classNameIdent)
|
let nimObj = new(classNameIdent)
|
||||||
setGodotObject(nimObj, obj)
|
nimObj.setOwn()
|
||||||
|
nimObj.setGodotObject(obj)
|
||||||
GC_ref(nimObj)
|
GC_ref(nimObj)
|
||||||
result = cast[pointer](nimObj)
|
result = cast[pointer](nimObj)
|
||||||
|
|
||||||
|
|
@ -281,7 +294,7 @@ template registerGodotClass(classNameIdent, classNameLit,
|
||||||
createFunc: createFuncIdent
|
createFunc: createFuncIdent
|
||||||
)
|
)
|
||||||
let destroyFuncObj = GodotInstanceDestroyFunc(
|
let destroyFuncObj = GodotInstanceDestroyFunc(
|
||||||
destroyFunc: nimDestroyFunc
|
destroyFunc: when isRef: nimDestroyRefFunc else: nimDestroyFunc
|
||||||
)
|
)
|
||||||
registerClass(classNameIdent, classNameLit, false)
|
registerClass(classNameIdent, classNameLit, false)
|
||||||
godotScriptRegisterClass(getNativeLibHandle(), classNameLit, baseNameLit,
|
godotScriptRegisterClass(getNativeLibHandle(), classNameLit, baseNameLit,
|
||||||
|
|
@ -328,7 +341,7 @@ template registerGodotField(classNameLit, classNameIdent, propNameLit,
|
||||||
godotScriptRegisterProperty(getNativeLibHandle(), classNameLit, propNameLit,
|
godotScriptRegisterProperty(getNativeLibHandle(), classNameLit, propNameLit,
|
||||||
attr, setFunc, getFunc)
|
attr, setFunc, getFunc)
|
||||||
static:
|
static:
|
||||||
import strutils
|
import strutils, sets
|
||||||
proc toGodotStyle(s: string): string {.compileTime.} =
|
proc toGodotStyle(s: string): string {.compileTime.} =
|
||||||
result = newStringOfCap(s.len + 10)
|
result = newStringOfCap(s.len + 10)
|
||||||
for c in s:
|
for c in s:
|
||||||
|
|
@ -385,12 +398,14 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
||||||
result.add(meth.nimNode)
|
result.add(meth.nimNode)
|
||||||
|
|
||||||
# 4. Register Godot object
|
# 4. Register Godot object
|
||||||
let parentName = if obj.parentName.isNil: newNilLit()
|
let parentName = if obj.parentName.isNil: newStrLitNode("Object")
|
||||||
else: newStrLitNode(obj.parentName)
|
else: newStrLitNode(obj.parentName)
|
||||||
let classNameLit = newCStringLit(obj.name)
|
let classNameLit = newCStringLit(obj.name)
|
||||||
let classNameIdent = ident(obj.name)
|
let classNameIdent = ident(obj.name)
|
||||||
|
let isRef: bool = if obj.parentName.isNil: false
|
||||||
|
else: obj.parentName in refClasses
|
||||||
result.add(getAst(
|
result.add(getAst(
|
||||||
registerGodotClass(classNameIdent, classNameLit, parentName,
|
registerGodotClass(classNameIdent, classNameLit, isRef, parentName,
|
||||||
genSym(nskProc, "createFunc"))))
|
genSym(nskProc, "createFunc"))))
|
||||||
|
|
||||||
# 5. Register fields (properties)
|
# 5. Register fields (properties)
|
||||||
|
|
@ -467,6 +482,20 @@ proc genType(obj: ObjectDecl): NimNode {.compileTime.} =
|
||||||
argTypes, genSym(nskProc, "methFunc"),
|
argTypes, genSym(nskProc, "methFunc"),
|
||||||
hasReturnValue)))
|
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 =
|
macro gdobj*(definition: untyped, body: untyped): typed =
|
||||||
let typeDef = parseType(definition, callsite())
|
let typeDef = parseType(definition, callsite())
|
||||||
result = genType(typeDef)
|
result = genType(typeDef)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ import "../core/strings.nim", "../core/vector2.nim", "../core/rect2.nim",
|
||||||
type
|
type
|
||||||
NimGodotObject* = ref object of RootObj
|
NimGodotObject* = ref object of RootObj
|
||||||
godotObject: ptr GodotObject
|
godotObject: ptr GodotObject
|
||||||
isRef: bool
|
isExternalRef: bool
|
||||||
|
isOwn: bool
|
||||||
|
|
||||||
ConversionResult* {.pure.} = enum
|
ConversionResult* {.pure.} = enum
|
||||||
OK,
|
OK,
|
||||||
|
|
@ -51,7 +52,8 @@ var classRegistry {.threadvar.}: TableRef[cstring, ObjectInfo]
|
||||||
|
|
||||||
static:
|
static:
|
||||||
import sets, strutils
|
import sets, strutils
|
||||||
var nativeClasses {.compileTime.} = initSet[string]()
|
var nativeClasses {.compileTime.} = newSeq[string]()
|
||||||
|
var refClasses* {.compileTime.} = newSeq[string]()
|
||||||
|
|
||||||
var getClassMethodBind {.threadvar.}: ptr GodotMethodBind
|
var getClassMethodBind {.threadvar.}: ptr GodotMethodBind
|
||||||
proc getClassName*(o: ptr GodotObject): string =
|
proc getClassName*(o: ptr GodotObject): string =
|
||||||
|
|
@ -87,7 +89,9 @@ proc deinit*(obj: NimGodotObject) =
|
||||||
|
|
||||||
proc godotFinalizer[T: NimGodotObject](obj: T) =
|
proc godotFinalizer[T: NimGodotObject](obj: T) =
|
||||||
if obj.godotObject.isNil: return
|
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()
|
obj.deinit()
|
||||||
|
|
||||||
macro baseNativeType(T: typedesc): cstring =
|
macro baseNativeType(T: typedesc): cstring =
|
||||||
|
|
@ -139,9 +143,12 @@ template registerClass*(T: typedesc; godotClassName: cstring,
|
||||||
isNative: isNativeParam,
|
isNative: isNativeParam,
|
||||||
isRef: isRef
|
isRef: isRef
|
||||||
)
|
)
|
||||||
|
when isRef:
|
||||||
|
static:
|
||||||
|
refClasses.add(T.name)
|
||||||
when isNativeParam:
|
when isNativeParam:
|
||||||
static:
|
static:
|
||||||
nativeClasses.incl(T.name)
|
nativeClasses.add(T.name)
|
||||||
|
|
||||||
proc newNimGodotObject[T: NimGodotObject](
|
proc newNimGodotObject[T: NimGodotObject](
|
||||||
godotObject: ptr GodotObject, godotClassName: cstring): T =
|
godotObject: ptr GodotObject, godotClassName: cstring): T =
|
||||||
|
|
@ -154,7 +161,7 @@ proc newNimGodotObject[T: NimGodotObject](
|
||||||
result = T(objInfo.constructor())
|
result = T(objInfo.constructor())
|
||||||
result.godotObject = godotObject
|
result.godotObject = godotObject
|
||||||
if objInfo.isRef:
|
if objInfo.isRef:
|
||||||
result.isRef = true
|
result.isExternalRef = true
|
||||||
result.godotObject.reference()
|
result.godotObject.reference()
|
||||||
|
|
||||||
proc asNimGodotObject*[T: NimGodotObject](godotObject: ptr GodotObject): T =
|
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
|
assert(nimObj.godotObject.isNil) # reassignment is not allowed
|
||||||
nimObj.godotObject = obj
|
nimObj.godotObject = obj
|
||||||
|
|
||||||
|
proc setOwn*(nimObj: NimGodotObject) {.inline.} =
|
||||||
|
nimObj.isOwn = true
|
||||||
|
|
||||||
proc godotObject*(nimObj: NimGodotObject): ptr GodotObject {.inline.} =
|
proc godotObject*(nimObj: NimGodotObject): ptr GodotObject {.inline.} =
|
||||||
nimObj.godotObject
|
nimObj.godotObject
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue