Skip to content

Commit 9a8429c

Browse files
committed
Finally ! Calling class method the hard way is working !
1 parent fa22d53 commit 9a8429c

File tree

13 files changed

+288
-62
lines changed

13 files changed

+288
-62
lines changed

scripts/extension_api_parser/api.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ def float_spec(self):
174174
return TYPES_DB["float"]
175175
# return next(builtin for builtin in self.builtins if builtin.name == "int")
176176

177+
def get_class_meth_hash(self, classname: str, methname: str) -> int:
178+
klass = next(c for c in self.classes if c.original_name == classname)
179+
meth = next(m for m in klass.methods if m.original_name == methname)
180+
return meth.hash
181+
177182

178183
def merge_builtins_size_info(api_json: dict, build_config: BuildConfig) -> None:
179184
# Builtins size depend of the build config, hence it is stored separatly from

src/_pythonscript.pyx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ from godot.builtins cimport GDString, Vector2
2727

2828
from godot.hazmat.gdnative_interface cimport *
2929
from godot.hazmat.gdapi cimport *
30-
30+
from godot.classes cimport _load_class
3131

3232
# include "_pythonscript_script.pxi"
3333
# include "_pythonscript_instance.pxi"
@@ -50,18 +50,32 @@ cdef api void _pythonscript_free_instance(
5050
# is the very first Python module that gets loaded.
5151

5252

53-
cdef api void _pythonscript_initialize() with gil:
53+
cdef api void _pythonscript_late_init() with gil:
54+
pythonscript_gdapi.print_error("pythonscript late init", "<function>", "<file>", 0)
55+
OS = _load_class("OS")
56+
pythonscript_gdapi.print_error("OS class loaded", "<function>", "<file>", 0)
57+
58+
# from godot.classes import OS
59+
cdef gd_variant_t gdvariant
60+
if not pyobject_to_gdvariant(f"singletion is {OS!r}", &gdvariant):
61+
pythonscript_gdapi.print_error("pyobject_to_gdvariant !!!!", "<function>", "<file>", 0)
62+
gd_print(&gdvariant, 1)
63+
pythonscript_gdapi.variant_destroy(&gdvariant)
64+
pythonscript_gdapi.print_error("_pythonscript_late_init done", "<function>", "<file>", 0)
65+
5466
import sys
5567
from godot._version import __version__ as pythonscript_version
56-
cdef GDString r = GDString("foo")
57-
if r.to_pystr() == "foo":
58-
pythonscript_gdapi.print_error("ok", "<function>", "<file>", 0)
59-
else:
60-
pythonscript_gdapi.print_error("ko", "<function>", "<file>", 0)
6168

6269
cooked_sys_version = '.'.join(map(str, sys.version_info))
6370
print(f"Pythonscript {pythonscript_version} (CPython {cooked_sys_version})")
6471
print(f"PYTHONPATH: {sys.path}")
72+
73+
74+
cdef api void _pythonscript_early_init() with gil:
75+
pythonscript_gdapi.print_error("pythonscript early init", "<function>", "<file>", 0)
76+
# pythonscript_gdapi.
77+
# Engine get_singleton_list
78+
6579
v = Vector2(66.8, -77.99)
6680
v.x = 42
6781
print("===========>", v.x, v.y)

src/godot/__init__.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,18 @@
3333
# exposed,
3434
# )
3535
from godot.builtins import *
36-
from godot.classes import *
36+
37+
# from godot.classes import _load_singleton, _load_class
38+
39+
40+
# def __getattr__(name):
41+
# # Look for singleton first given they have the same name than their class
42+
# item = _load_singleton(name) or _load_class(name)
43+
44+
# if not item:
45+
# raise AttributeError
46+
47+
# # Cache entry
48+
# setattr(globals(), name, item)
49+
50+
# return item

src/godot/builtins_pyx/class.pyx.j2

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
{% else %}
99
@property
1010
def {{ c.name }}(self):
11-
return {{ c.value }}
11+
cdef gd_variant_t gdvariant
12+
pythonscript_gdapi.variant_get_constant_value({{ spec.variant_type_name }}, "{{ c.original_name }}", &gdvariant)
13+
try:
14+
return gdvariant_to_pyobject(&gdvariant)
15+
finally:
16+
gd_variant_del(&gdvariant)
1217
{% endif %}
1318
{% endmacro %}
1419

@@ -30,9 +35,12 @@ cdef class {{ spec.name }}:
3035
{% endif %}
3136

3237
def __repr__(self):
33-
# TODO: finish me...
34-
# pythonscript_gdapi.variant_stringify(&self._gd_data)
35-
return "<{{ spec.name }}>"
38+
cdef gd_string_t gdstr
39+
try:
40+
pythonscript_gdapi.variant_stringify(&self._gd_data, &gdstr)
41+
return gdstring_to_pystr(&gdstr)
42+
finally:
43+
gd_string_del(&gdstr)
3644
{% if spec.name == "GDString" %}
3745
def __str__(self):
3846
return self.to_pystr()

src/godot/classes.pxd.j2

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ cdef class {{spec.name}}({{ spec.inherits or "" }}):
3939
pass
4040
{% endif %}
4141
{% endfor %}
42+
43+
44+
cdef object _load_class(str name)
45+
cdef object _object_call(GDNativeObjectPtr obj, str meth, args)

src/godot/classes.pyx.j2

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,21 @@
33

44
cimport cython
55

6-
from .hazmat.gdapi cimport pythonscript_gdapi
7-
from .hazmat.gdnative_interface cimport GDNativeObjectPtr
6+
from .hazmat.gdapi cimport *
7+
from .builtins cimport *
88
{% for spec in api["classes"] %}
99

1010

1111
cdef class {{ spec.name }}({{ spec.inherits or "" }}):
1212
{% if spec.inherits is none %}
13+
14+
{# @staticmethod
15+
cpdef inline {{ spec.name}} new():
16+
raise NotImplementedError("TODO :'(") #}
17+
1318
def free(self):
14-
gdobject_free(self)
19+
pythonscript_gdapi.object_destroy(self._gd_ptr)
20+
self._gd_ptr = NULL
1521

1622
def __init__(self):
1723
raise RuntimeError(
@@ -24,3 +30,68 @@ cdef class {{ spec.name }}({{ spec.inherits or "" }}):
2430
pass
2531
{% endif %}
2632
{% endfor %}
33+
34+
35+
cdef _load_singleton(name):
36+
cdef GDObject gdobj = GDObject.__new__(GDObject)
37+
gdobj._gd_ptr = pythonscript_gdapi.global_get_singleton(name)
38+
{% for spec in api["singletons"] %}
39+
cdef {{ spec.type.py_type }} singleton_{{ spec.name }} = {{ spec.type.py_type }}.__new__({{ spec.type.py_type }})
40+
singleton_{{ spec.name }}._gd_ptr = pythonscript_gdapi.global_get_singleton("{{ spec.original_name }}")
41+
globals()["{{ spec.name }}"] = singleton_{{ spec.name }}
42+
{% endfor %}
43+
44+
45+
cdef object _load_class(str name):
46+
# Load our good friend ClassDB
47+
cdef GDNativeObjectPtr classdb = pythonscript_gdapi.global_get_singleton("ClassDB")
48+
pythonscript_gdapi.print_error("AAAAAAAAAA", "_object_call", "", 0)
49+
cdef gd_variant_t meths = _object_call(classdb, "class_get_method_list", [name])
50+
pythonscript_gdapi.print_error("BBBB", "_object_call", "", 0)
51+
pythonscript_gdapi.print_error("GOOOOOOOOOOOOOOOD", "_object_call", "", 0)
52+
53+
54+
cdef object _object_call(GDNativeObjectPtr obj, str meth, args):
55+
cdef gd_variant_t ret
56+
cdef GDNativeCallError call_error
57+
58+
cdef GDNativeObjectPtr classdb = pythonscript_gdapi.global_get_singleton("ClassDB")
59+
cdef GDNativeMethodBindPtr Object_call = pythonscript_gdapi.classdb_get_method_bind("Object", "call", {{ api.get_class_meth_hash("Object", "call") }})
60+
61+
cdef GDNativeInt args_with_meth_len = len(args) + 1
62+
if args_with_meth_len > 9:
63+
# TODO: handle this
64+
pythonscript_gdapi.print_error("more than 8 params is not supported !", "_object_call", "", 0)
65+
return None
66+
cdef gd_variant_t[9] variant_args
67+
cdef (gd_variant_t*)[9] variant_args_ptrs
68+
for i in range(args_with_meth_len):
69+
variant_args_ptrs[i] = &variant_args[i]
70+
71+
cdef gd_string_t meth_gdstr = gdstring_from_unchecked_pystr(meth)
72+
cdef gd_string_name_t meth_gdstrname = gd_string_name_new_from_string(&meth_gdstr)
73+
gd_string_del(&meth_gdstr)
74+
variant_args[0] = gd_string_name_into_variant(&meth_gdstrname)
75+
# Into conversion steals the owneship, so no need to delete meth_gdstrname
76+
77+
for i, arg in enumerate(args, 1):
78+
# TODO: check return value
79+
pyobject_to_gdvariant(arg, &variant_args[i])
80+
81+
pythonscript_gdapi.object_method_bind_call(
82+
Object_call,
83+
classdb,
84+
<GDNativeVariantPtr *>&variant_args_ptrs,
85+
args_with_meth_len,
86+
&ret,
87+
&call_error, # TODO: check call_error
88+
)
89+
pythonscript_gdapi.print_error("after call", "<function>", "<file>", 0)
90+
for i in range(args_with_meth_len):
91+
gd_variant_del(&variant_args[i])
92+
93+
try:
94+
gd_print(&ret, 1)
95+
return gdvariant_to_pyobject(&ret)
96+
finally:
97+
gd_variant_del(&ret)

src/godot/hazmat/gdapi.pxd.j2

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
render_utility_function,
44
render_builtin_type_cy_struct,
55
render_builtin_type_c_extern,
6+
render_builtin_into_variant_signature,
7+
render_builtin_from_variant_signature,
68
render_builtin_constructor_signature,
79
render_builtin_destructor_signature,
810
render_builtin_method_signature,
@@ -60,10 +62,15 @@ cdef extern from *:
6062
{% endfor %}
6163

6264

65+
# gd_variant_del(gd_variant_t *variant)
66+
# GDNativeObjectPtr gd_object_from_variant(gd_variant_t *val)
67+
# gd_variant_t gd_object_into_variant(GDNativeObjectPtr *val)
6368
{% for spec in api["builtins"] if not spec.is_scalar %}
6469

6570

6671
# {{spec.original_name }}: List of inlines functions defined in the jungle below
72+
# {{ render_builtin_into_variant_signature(spec) }}
73+
# {{ render_builtin_from_variant_signature(spec) }}
6774
{% for c in spec.constructors %}
6875
# {{ render_builtin_constructor_signature(spec, c) }}
6976
{% endfor %}
@@ -129,6 +136,10 @@ DEF {{ key }} = {{ value }}
129136
# and nicer inline function
130137

131138

139+
cdef inline gd_variant_del(gd_variant_t *variant):
140+
pythonscript_gdapi.variant_destroy(variant)
141+
142+
132143
##############################################################################
133144
# Inline defs: Utility functions #
134145
##############################################################################
@@ -208,5 +219,5 @@ DEF {{ spec.c_name_prefix.upper() }}_{{ key }} = {{ value }}
208219

209220
{% for spec in api["builtins"] if not spec.is_scalar %}
210221
cdef GDNativeTypeFromVariantConstructorFunc __{{ spec.name }}_from_variant
211-
cdef GDNativeVariantFromTypeConstructorFunc __{{ spec.name }}_to_variant
222+
cdef GDNativeVariantFromTypeConstructorFunc __{{ spec.name }}_into_variant
212223
{% endfor %}

src/godot/hazmat/gdapi_pxd/conversion.pxd.j2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
cdef object gdvariant_to_pyobj(const gd_variant_t *p_gdvar)
2-
cdef bint pyobj_to_gdvariant(object pyobj, gd_variant_t *p_var)
1+
cdef object gdvariant_to_pyobject(const gd_variant_t *p_gdvar)
2+
cdef bint pyobject_to_gdvariant(object pyobj, gd_variant_t *p_var)
33

44

55
cdef bint is_pytype_compatible_with_gdvariant(object pytype)

0 commit comments

Comments
 (0)