From 3179fe225f6ee4f8598bf5875c56ceb41ee2b4fa Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sun, 16 Aug 2020 22:57:07 -0500 Subject: [PATCH] Add comments to simple.c and simplify it The comments are from the documentation article. --- c/simple/src/simple.c | 49 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/c/simple/src/simple.c b/c/simple/src/simple.c index 451d51b..1561b27 100644 --- a/c/simple/src/simple.c +++ b/c/simple/src/simple.c @@ -1,23 +1,30 @@ #include -#include -#include #include typedef struct user_data_struct { char data[256]; } user_data_struct; +// GDNative supports a large collection of functions for calling back +// into the main Godot executable. In order for your module to have +// access to these functions, GDNative provides your application with +// a struct containing pointers to all these functions. const godot_gdnative_core_api_struct *api = NULL; const godot_gdnative_ext_nativescript_api_struct *nativescript_api = NULL; +// These are forward declarations for the functions we'll be implementing +// for our object. A constructor and destructor are both necessary. GDCALLINGCONV void *simple_constructor(godot_object *p_instance, void *p_method_data); GDCALLINGCONV void simple_destructor(godot_object *p_instance, void *p_method_data, void *p_user_data); godot_variant simple_get_data(godot_object *p_instance, void *p_method_data, void *p_user_data, int p_num_args, godot_variant **p_args); +// `gdnative_init` is a function that initializes our dynamic library. +// Godot will give it a pointer to a structure that contains various bits of +// information we may find useful among which the pointers to our API structures. void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *p_options) { api = p_options->api_struct; - // now find our extensions + // Find NativeScript extensions. for (int i = 0; i < api->num_extensions; i++) { switch (api->extensions[i]->type) { case GDNATIVE_EXT_NATIVESCRIPT: { @@ -29,11 +36,16 @@ void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *p_options) { }; } +// `gdnative_terminate` which is called before the library is unloaded. +// Godot will unload the library when no object uses it anymore. void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *p_options) { api = NULL; nativescript_api = NULL; } +// `nativescript_init` is the most important function. Godot calls +// this function as part of loading a GDNative library and communicates +// back to the engine what objects we make available. void GDN_EXPORT godot_nativescript_init(void *p_handle) { godot_instance_create_func create = { NULL, NULL, NULL }; create.create_func = &simple_constructor; @@ -41,6 +53,13 @@ void GDN_EXPORT godot_nativescript_init(void *p_handle) { godot_instance_destroy_func destroy = { NULL, NULL, NULL }; destroy.destroy_func = &simple_destructor; + // We first tell the engine which classes are implemented by calling this. + // * The first parameter here is the handle pointer given to us. + // * The second is the name of our object class. + // * The third is the type of object in Godot that we 'inherit' from; + // this is not true inheritance but it's close enough. + // * Finally, the fourth and fifth parameters are descriptions + // for our constructor and destructor, respectively. nativescript_api->godot_nativescript_register_class(p_handle, "SIMPLE", "Reference", create, destroy); godot_instance_method get_data = { NULL, NULL, NULL }; @@ -48,24 +67,40 @@ void GDN_EXPORT godot_nativescript_init(void *p_handle) { godot_method_attributes attributes = { GODOT_METHOD_RPC_MODE_DISABLED }; + // We then tell Godot about our methods by calling this for each + // method of our class. In our case, this is just `get_data`. + // * Our first parameter is yet again our handle pointer. + // * The second is again the name of the object class we're registering. + // * The third is the name of our function as it will be known to GDScript. + // * The fourth is our attributes setting (see godot_method_rpc_mode enum in + // `godot_headers/nativescript/godot_nativescript.h` for possible values). + // * The fifth and final parameter is a description of which function + // to call when the method gets called. nativescript_api->godot_nativescript_register_method(p_handle, "SIMPLE", "get_data", attributes, get_data); } +// In our constructor, allocate memory for our structure and fill +// it with some data. Note that we use Godot's memory functions +// so the memory gets tracked and then return the pointer to +// our new structure. This pointer will act as our instance +// identifier in case multiple objects are instantiated. GDCALLINGCONV void *simple_constructor(godot_object *p_instance, void *p_method_data) { - printf("SIMPLE._init()\n"); - user_data_struct *user_data = api->godot_alloc(sizeof(user_data_struct)); strcpy(user_data->data, "World from GDNative!"); return user_data; } +// The destructor is called when Godot is done with our +// object and we free our instances' member data. GDCALLINGCONV void simple_destructor(godot_object *p_instance, void *p_method_data, void *p_user_data) { - printf("SIMPLE._byebye()\n"); - api->godot_free(p_user_data); } +// Data is always sent and returned as variants so in order to +// return our data, which is a string, we first need to convert +// our C string to a Godot string object, and then copy that +// string object into the variant we are returning. godot_variant simple_get_data(godot_object *p_instance, void *p_method_data, void *p_user_data, int p_num_args, godot_variant **p_args) { godot_string data; godot_variant ret;