Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibGodot Feature #35

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,14 @@ opts.Add("custom_modules", "A list of comma-separated directory paths containing
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))

# Advanced options
opts.Add(
EnumVariable(
"library_type",
"Build library type",
"executable",
("executable", "static_library", "shared_library"),
)
)
opts.Add(BoolVariable("dev_mode", "Alias for dev options: verbose=yes warnings=extra werror=yes tests=yes", False))
opts.Add(BoolVariable("tests", "Build the unit tests", False))
opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster rebuilds", False))
Expand Down Expand Up @@ -302,6 +310,15 @@ if env["import_env_vars"]:

selected_platform = env["platform"]

if env["library_type"] == "static_library":
env.Append(CPPDEFINES=["LIBRARY_ENABLED"])
elif env["library_type"] == "shared_library":
env.Append(CPPDEFINES=["LIBRARY_ENABLED"])
env.Append(CCFLAGS=["-fPIC"])
env.Append(STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME=True)
else:
env.__class__.add_program = methods.add_program

if env.scons_version < (4, 3) and not selected_platform:
selected_platform = env["p"]

Expand Down
5 changes: 5 additions & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ const PackedStringArray ProjectSettings::get_required_features() {
// Returns the features supported by this build of Godot. Includes all required features.
const PackedStringArray ProjectSettings::_get_supported_features() {
PackedStringArray features = get_required_features();

#ifdef LIBRARY_ENABLED
features.append("Embedded");
#endif

#ifdef MODULE_MONO_ENABLED
features.append("C#");
#endif
Expand Down
24 changes: 18 additions & 6 deletions core/extension/gdextension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,9 +810,14 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb
}

GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr;
GDExtensionBool ret = initialization_function(&gdextension_get_proc_address, this, &initialization);
return initialize_extension_function(initialization_function, p_entry_symbol);
}

if (ret) {
Error GDExtension::initialize_extension_function(GDExtensionInitializationFunction initialization_function, const String &p_entry_symbol) {
if (library == nullptr) {
embedded = true;
}
if (initialization_function(&gdextension_get_proc_address, this, &initialization)) {
level_initialized = -1;
return OK;
} else {
Expand All @@ -823,6 +828,9 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb
}

void GDExtension::close_library() {
if (embedded) {
return;
}
ERR_FAIL_NULL(library);
OS::get_singleton()->close_dynamic_library(library);

Expand All @@ -834,17 +842,21 @@ void GDExtension::close_library() {
#endif
}

bool GDExtension::is_embedded() const {
return embedded;
}

bool GDExtension::is_library_open() const {
return library != nullptr;
return (library != nullptr) || embedded;
}

GDExtension::InitializationLevel GDExtension::get_minimum_library_initialization_level() const {
ERR_FAIL_NULL_V(library, INITIALIZATION_LEVEL_CORE);
ERR_FAIL_COND_V(library == nullptr && !embedded, INITIALIZATION_LEVEL_CORE);
return InitializationLevel(initialization.minimum_initialization_level);
}

void GDExtension::initialize_library(InitializationLevel p_level) {
ERR_FAIL_NULL(library);
ERR_FAIL_COND(library == nullptr && !embedded);
ERR_FAIL_COND_MSG(p_level <= int32_t(level_initialized), vformat("Level '%d' must be higher than the current level '%d'", p_level, level_initialized));

level_initialized = int32_t(p_level);
Expand All @@ -854,7 +866,7 @@ void GDExtension::initialize_library(InitializationLevel p_level) {
initialization.initialize(initialization.userdata, GDExtensionInitializationLevel(p_level));
}
void GDExtension::deinitialize_library(InitializationLevel p_level) {
ERR_FAIL_NULL(library);
ERR_FAIL_COND(library == nullptr && !embedded);
ERR_FAIL_COND(p_level > int32_t(level_initialized));

level_initialized = int32_t(p_level) - 1;
Expand Down
3 changes: 3 additions & 0 deletions core/extension/gdextension.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class GDExtension : public Resource {

friend class GDExtensionManager;

bool embedded = false;
void *library = nullptr; // pointer if valid,
String library_path;
bool reloadable = false;
Expand Down Expand Up @@ -127,6 +128,7 @@ class GDExtension : public Resource {
static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
static Vector<SharedObject> find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature);

Error initialize_extension_function(GDExtensionInitializationFunction initialization_function, const String &p_entry_symbol);
Error open_library(const String &p_path, const String &p_entry_symbol, Vector<SharedObject> *p_dependencies = nullptr);
void close_library();

Expand All @@ -137,6 +139,7 @@ class GDExtension : public Resource {
INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR
};

bool is_embedded() const;
bool is_library_open() const;

#ifdef TOOLS_ENABLED
Expand Down
17 changes: 17 additions & 0 deletions core/extension/gdextension_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "core/config/engine.h"
#include "core/extension/gdextension.h"
#include "core/extension/gdextension_compat_hashes.h"
#include "core/extension/godot_runtime_api.h"
#include "core/io/file_access.h"
#include "core/io/xml_parser.h"
#include "core/object/class_db.h"
Expand Down Expand Up @@ -1504,6 +1505,20 @@ static void *gdextension_classdb_get_class_tag(GDExtensionConstStringNamePtr p_c
return class_info ? class_info->class_ptr : nullptr;
}

GDExtensionObjectPtr gdextension_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func) {
#ifdef LIBRARY_ENABLED
return create_godot_instance(p_argc, p_argv, p_init_func);
#else
return nullptr;
#endif
}

static void gdextension_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance) {
#ifdef LIBRARY_ENABLED
destroy_godot_instance(p_godot_instance);
#endif
}

static void gdextension_editor_add_plugin(GDExtensionConstStringNamePtr p_classname) {
#ifdef TOOLS_ENABLED
const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
Expand Down Expand Up @@ -1684,6 +1699,8 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(editor_remove_plugin);
REGISTER_INTERFACE_FUNC(editor_help_load_xml_from_utf8_chars);
REGISTER_INTERFACE_FUNC(editor_help_load_xml_from_utf8_chars_and_len);
REGISTER_INTERFACE_FUNC(create_godot_instance);
REGISTER_INTERFACE_FUNC(destroy_godot_instance);
}

#undef REGISTER_INTERFACE_FUNCTION
8 changes: 8 additions & 0 deletions core/extension/gdextension_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -2892,6 +2892,14 @@ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);

typedef GDExtensionObjectPtr (*GDExtensionInterfaceCreateGodotInstance)(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func);
typedef void (*GDExtensionInterfaceDestroyGodotInstance)(GDExtensionObjectPtr p_godot_instance);

#if defined(_WIN32)
__declspec(dllexport)
#endif
GDExtensionObjectPtr gdextension_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func);

#ifdef __cplusplus
}
#endif
Expand Down
14 changes: 13 additions & 1 deletion core/extension/gdextension_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ void GDExtensionManager::_reload_all_scripts() {
}
#endif // TOOLS_ENABLED

void GDExtensionManager::load_extensions() {
void GDExtensionManager::load_extensions(GDExtensionInitializationFunction p_init_func) {
Ref<FileAccess> f = FileAccess::open(GDExtension::get_extension_list_config_file(), FileAccess::READ);
while (f.is_valid() && !f->eof_reached()) {
String s = f->get_line().strip_edges();
Expand All @@ -236,6 +236,18 @@ void GDExtensionManager::load_extensions() {
}

OS::get_singleton()->load_platform_gdextensions();

if (p_init_func) {
Ref<GDExtension> libgodot;
libgodot.instantiate();
Error err = libgodot->initialize_extension_function(p_init_func, "lib_godot");
if (err != OK) {
ERR_PRINT("Error initializing extension function");
} else {
libgodot->set_path("res://__LibGodot");
GDExtensionManager::get_singleton()->load_extension("res://__LibGodot");
}
}
}

void GDExtensionManager::reload_extensions() {
Expand Down
2 changes: 1 addition & 1 deletion core/extension/gdextension_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class GDExtensionManager : public Object {

static GDExtensionManager *get_singleton();

void load_extensions();
void load_extensions(GDExtensionInitializationFunction p_init_func = nullptr);
void reload_extensions();

GDExtensionManager();
Expand Down
69 changes: 69 additions & 0 deletions core/extension/godot_instance.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**************************************************************************/
/* godot_instance.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "godot_instance.h"
#include "main/main.h"
#include "servers/display_server.h"

void GodotInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("start"), &GodotInstance::start);
ClassDB::bind_method(D_METHOD("is_started"), &GodotInstance::is_started);
ClassDB::bind_method(D_METHOD("iteration"), &GodotInstance::iteration);
ClassDB::bind_method(D_METHOD("shutdown"), &GodotInstance::shutdown);
}

GodotInstance::GodotInstance() {
}

GodotInstance::~GodotInstance() {
}

bool GodotInstance::start() {
Error err = Main::setup2();
if (err != OK) {
return false;
}
started = Main::start() == EXIT_SUCCESS;
return started;
}

bool GodotInstance::is_started() {
return started;
}

bool GodotInstance::iteration() {
DisplayServer::get_singleton()->process_events();
return Main::iteration();
}

void GodotInstance::shutdown() {
started = false;
Main::cleanup();
}
55 changes: 55 additions & 0 deletions core/extension/godot_instance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**************************************************************************/
/* godot_instance.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef GODOT_INSTANCE_H
#define GODOT_INSTANCE_H

#include "core/error/error_list.h"
#include "core/object/class_db.h"
#include "core/object/object.h"

class GodotInstance : public Object {
GDCLASS(GodotInstance, Object);

static void _bind_methods();

bool started = false;

public:
GodotInstance();
~GodotInstance();

virtual bool start();
virtual bool is_started();
virtual bool iteration();
virtual void shutdown();
};

#endif // GODOT_INSTANCE_H
40 changes: 40 additions & 0 deletions core/extension/godot_runtime_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**************************************************************************/
/* godot_runtime_api.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef GODOT_RUNTIME_API_H
#define GODOT_RUNTIME_API_H

#include "core/extension/gdextension_interface.h"

GDExtensionObjectPtr create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func);

void destroy_godot_instance(GDExtensionObjectPtr p_godot_instance);

#endif // GODOT_RUNTIME_API_H
Loading
Loading