Skip to content

Commit

Permalink
Draft of builtin vararg call.
Browse files Browse the repository at this point in the history
  • Loading branch information
PapyChacal committed Sep 27, 2022
1 parent bef1fa0 commit a616159
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 13 deletions.
113 changes: 109 additions & 4 deletions binding_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pathlib import Path


def get_file_list(api_filepath, output_dir, headers=False, sources=False):
def get_file_list(api_filepath, output_dir, headers=False, sources=False, impl=True):
api = {}
files = []
with open(api_filepath) as api_file:
Expand All @@ -23,11 +23,18 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
continue

header_filename = include_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".hpp")
implid_filename = include_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".impl")
source_filename = source_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".cpp")
if headers:
files.append(str(header_filename.as_posix()))
if sources:
files.append(str(source_filename.as_posix()))
if impl:
has_impl = false
for method in builtin_class["methods"]:
if method["is_vararg"]:
has_impl = true
files.append(str(implid_filename.as_posix()))

for engine_class in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
Expand Down Expand Up @@ -64,14 +71,14 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
return files


def print_file_list(api_filepath, output_dir, headers=False, sources=False):
def print_file_list(api_filepath, output_dir, headers=False, sources=False, impl=True):
end = ";"
for f in get_file_list(api_filepath, output_dir, headers, sources):
for f in get_file_list(api_filepath, output_dir, headers, sources, impl):
print(f, end=end)


def scons_emit_files(target, source, env):
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True)]
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True, True)]
env.Clean(files, target)
return [target[0]] + files, source

Expand Down Expand Up @@ -155,6 +162,8 @@ def generate_builtin_bindings(api, output_dir, build_config):

variant_size_file.write("\n".join(variant_size_source))

implid_builtins = set()

for builtin_api in api["builtin_classes"]:
if is_pod_type(builtin_api["name"]):
continue
Expand All @@ -164,12 +173,16 @@ def generate_builtin_bindings(api, output_dir, build_config):
size = builtin_sizes[builtin_api["name"]]

header_filename = include_gen_folder / (camel_to_snake(builtin_api["name"]) + ".hpp")
implid_filename = include_gen_folder / (camel_to_snake(builtin_api["name"]) + ".impl")
source_filename = source_gen_folder / (camel_to_snake(builtin_api["name"]) + ".cpp")

# Check used classes for header include
used_classes = set()
fully_used_classes = set()

# Check varargs methods for impl file gen
template_methods = list()

class_name = builtin_api["name"]

if "constructors" in builtin_api:
Expand All @@ -194,6 +207,8 @@ def generate_builtin_bindings(api, output_dir, build_config):
if "return_type" in method:
if is_included(method["return_type"], class_name):
used_classes.add(method["return_type"])
if method["is_vararg"]:
template_methods.append(method)

if "members" in builtin_api:
for member in builtin_api["members"]:
Expand All @@ -217,6 +232,11 @@ def generate_builtin_bindings(api, output_dir, build_config):
if type_name in used_classes:
used_classes.remove(type_name)

has_templates = len(template_methods) > 0

if has_templates:
implid_builtins.add(builtin_api["name"])

used_classes = list(used_classes)
used_classes.sort()
fully_used_classes = list(fully_used_classes)
Expand All @@ -227,6 +247,9 @@ def generate_builtin_bindings(api, output_dir, build_config):

with source_filename.open("w+") as source_file:
source_file.write(generate_builtin_class_source(builtin_api, size, used_classes, fully_used_classes))
if has_templates:
with implid_filename.open("w+") as impl_file:
impl_file.write(generate_builtin_class_impl(builtin_api, template_methods))

# Create a header with all builtin types for convenience.
builtin_header_filename = include_gen_folder / "builtin_types.hpp"
Expand Down Expand Up @@ -813,6 +836,88 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
return "\n".join(result)


def generate_builtin_class_impl(builtin_api, template_methods):
result = []

class_name = builtin_api["name"]
snake_class_name = camel_to_snake(class_name)
enum_type_name = f"GDNATIVE_VARIANT_TYPE_{snake_class_name.upper()}"

result.append("#include <godot_cpp/core/binder_common.hpp>")
result.append("")

result.append("#include <godot_cpp/core/builtin_ptrcall.hpp>")
result.append("")

for method in template_methods:
if "return_type" in method:
result.append(f'#include <godot_cpp/{get_include_path(method["return_type"])}>')
result.append("")

result.append("namespace godot {")
result.append("")

for method in template_methods:

result.append("template<class... Args>")

return_type = ""
if "return_type" in method:
return_type = method["return_type"]
else:
return_type = "void"

method_parameters = []
if "arguments" in method:
method_parameters = method["arguments"]
parameters = make_function_parameters(
method_parameters, include_default=False, for_builtin=False, is_vararg=True
)

const_qualifier = ""
if "is_const" in method and method["is_const"]:
const_qualifier = " const"

result.append(f'{return_type} {builtin_api["name"]}::{method["name"]}({parameters}){const_qualifier}')

result.append("{")

method_call = "\t"
if "return_type" in method:
method_call += f'return internal::_call_builtin_method_ret<{correct_type(method["return_type"])}>('
else:
method_call += f"internal::_call_builtin_method_no_ret("
method_call += f'_method_bindings.method_{method["name"]}, '
if "is_static" in method and method["is_static"]:
method_call += "nullptr"
else:
method_call += "_native_ptr()"

if "arguments" in method:
arguments = []
method_call += ", "
for argument in method["arguments"]:
(encode, arg_name) = get_encoded_arg(
argument["name"],
argument["type"],
argument["meta"] if "meta" in argument else None,
)
result += encode
arguments.append(arg_name)
method_call += ", ".join(arguments)
method_call += ", Variant(args)..."
method_call += ");"

result.append(method_call)

result.append("}")
result.append("")

result.append("} // namespace godot")

return "\n".join(result)


def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
global engine_classes
global singletons
Expand Down
25 changes: 18 additions & 7 deletions include/godot_cpp/core/builtin_ptrcall.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,35 @@ namespace internal {

template <class... Args>
void _call_builtin_constructor(const GDNativePtrConstructor constructor, GDNativeTypePtr base, Args... args) {
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
constructor(base, call_args.data());
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
constructor(base, call_args.data());
}

template <class T, class... Args>
T _call_builtin_method_ptr_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
T ret;
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
method(base, call_args.data(), &ret, sizeof...(Args));
T ret;
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
method(base, call_args.data(), &ret, sizeof...(Args));
return ret;
}

template <class T, class... Args>
T _call_builtin_method_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
return _call_builtin_method_ptr_ret<T, Args*...>(method, base, &args...);
}

template <class... Args>
void _call_builtin_method_ptr_no_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
method(base, call_args.data(), nullptr, sizeof...(Args));
std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
method(base, call_args.data(), nullptr, sizeof...(Args));
}

template <class... Args>
void _call_builtin_method_no_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
return _call_builtin_method_ptr_no_ret<Args...>(method, base, &args...);
}


template <class T>
T _call_builtin_operator_ptr(const GDNativePtrOperatorEvaluator op, const GDNativeTypePtr left, const GDNativeTypePtr right) {
T ret;
Expand Down
13 changes: 12 additions & 1 deletion include/godot_cpp/variant/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,24 @@

#include <godot_cpp/core/defs.hpp>

#include <godot_cpp/variant/builtin_types.hpp>
#include <godot_cpp/variant/variant_size.hpp>
#include <godot_cpp/variant/string.hpp>

#include <godot/gdnative_interface.h>

#include <array>

namespace godot {

class RID;
class Vector2;
class Vector3;
class Vector3i;
class Vector2i;
class Rect2;
class Rect2i;
class StringName;

class Variant {
uint8_t opaque[GODOT_CPP_VARIANT_SIZE]{ 0 };

Expand Down Expand Up @@ -320,4 +329,6 @@ struct VariantComparator {

} // namespace godot

#include <godot_cpp/variant/builtin_types.hpp>

#endif // ! GODOT_CPP_VARIANT_HPP
2 changes: 1 addition & 1 deletion misc/scripts/check_get_file_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
output_dir = "self_test"

generate_bindings(api_filepath, use_template_get_node=False, bits=bits, double=double, output_dir=output_dir)
flist = get_file_list(api_filepath, output_dir, headers=True, sources=True)
flist = get_file_list(api_filepath, output_dir, headers=True, sources=True, impl=True)

p = Path(output_dir) / "gen"
allfiles = [str(f.as_posix()) for f in p.glob("**/*.*")]
Expand Down

0 comments on commit a616159

Please sign in to comment.