diff --git a/.gitmodules b/.gitmodules index 5efb8ca..52f1507 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "c/SimpleDemo/godot_headers"] - path = c/SimpleDemo/godot_headers - url = https://github.com/GodotNativeTools/godot_headers +[submodule "c/simple/godot_headers"] + path = c/simple/godot_headers + url = https://github.com/godotengine/godot_headers diff --git a/c/SimpleDemo/demo/bin/simple.gdnlib b/c/SimpleDemo/demo/bin/simple.gdnlib deleted file mode 100644 index 84734e3..0000000 --- a/c/SimpleDemo/demo/bin/simple.gdnlib +++ /dev/null @@ -1,18 +0,0 @@ -[general] - -singleton=false -load_once=true -symbol_prefix="godot_" -reloadable=true - -[entry] - -X11.64="res://bin/x11/libsimple.so" -Windows.64="res://bin/win64/libsimple.dll" -OSX.64="res://bin/osx/libsimple.dylib" - -[dependencies] - -X11.64=[ ] -Windows=[ ] -OSX.64=[ ] diff --git a/c/SimpleDemo/demo/default_env.tres b/c/SimpleDemo/demo/default_env.tres deleted file mode 100644 index 1b9440d..0000000 --- a/c/SimpleDemo/demo/default_env.tres +++ /dev/null @@ -1,99 +0,0 @@ -[gd_resource type="Environment" load_steps=2 format=2] - -[sub_resource type="ProceduralSky" id=1] - -radiance_size = 1 -sky_top_color = Color( 0.301961, 0.403922, 0.909804, 1 ) -sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) -sky_curve = 0.25 -sky_energy = 1.0 -ground_bottom_color = Color( 0.196078, 0.152941, 0.0980392, 1 ) -ground_horizon_color = Color( 0.329412, 0.211765, 0.0627451, 1 ) -ground_curve = 0.25 -ground_energy = 1.0 -sun_color = Color( 1, 1, 1, 1 ) -sun_latitude = 35.0 -sun_longitude = 0.0 -sun_angle_min = 1.0 -sun_angle_max = 100.0 -sun_curve = 0.05 -sun_energy = 16.0 -texture_size = 0 - -[resource] - -background_mode = 2 -background_sky = SubResource( 1 ) -background_sky_scale = 1.0 -background_color = Color( 0, 0, 0, 1 ) -background_energy = 1.0 -background_canvas_max_layer = 0 -ambient_light_color = Color( 0, 0, 0, 1 ) -ambient_light_energy = 1.0 -ambient_light_sky_contribution = 0.0 -fog_enabled = false -fog_color = Color( 0.5, 0.6, 0.7, 1 ) -fog_sun_color = Color( 1, 0.9, 0.7, 1 ) -fog_sun_amount = 0.0 -fog_depth_enabled = true -fog_depth_begin = 10.0 -fog_depth_curve = 1.0 -fog_transmit_enabled = false -fog_transmit_curve = 1.0 -fog_height_enabled = false -fog_height_min = 0.0 -fog_height_max = 100.0 -fog_height_curve = 1.0 -tonemap_mode = 0 -tonemap_exposure = 1.0 -tonemap_white = 1.0 -auto_exposure_enabled = false -auto_exposure_scale = 0.4 -auto_exposure_min_luma = 0.05 -auto_exposure_max_luma = 8.0 -auto_exposure_speed = 0.5 -ss_reflections_enabled = false -ss_reflections_max_steps = 64 -ss_reflections_fade_in = 0.15 -ss_reflections_fade_out = 2.0 -ss_reflections_depth_tolerance = 0.2 -ss_reflections_roughness = true -ssao_enabled = false -ssao_radius = 1.0 -ssao_intensity = 1.0 -ssao_radius2 = 0.0 -ssao_intensity2 = 1.0 -ssao_bias = 0.01 -ssao_light_affect = 0.0 -ssao_color = Color( 0, 0, 0, 1 ) -ssao_blur = true -dof_blur_far_enabled = false -dof_blur_far_distance = 10.0 -dof_blur_far_transition = 5.0 -dof_blur_far_amount = 0.1 -dof_blur_far_quality = 1 -dof_blur_near_enabled = false -dof_blur_near_distance = 2.0 -dof_blur_near_transition = 1.0 -dof_blur_near_amount = 0.1 -dof_blur_near_quality = 1 -glow_enabled = false -glow_levels/1 = false -glow_levels/2 = false -glow_levels/3 = true -glow_levels/4 = false -glow_levels/5 = true -glow_levels/6 = false -glow_levels/7 = false -glow_intensity = 0.8 -glow_strength = 1.0 -glow_bloom = 0.0 -glow_blend_mode = 2 -glow_hdr_treshold = 1.0 -glow_hdr_scale = 2.0 -glow_bicubic_upscale = false -adjustment_enabled = false -adjustment_brightness = 1.0 -adjustment_contrast = 1.0 -adjustment_saturation = 1.0 - diff --git a/c/SimpleDemo/godot_headers b/c/SimpleDemo/godot_headers deleted file mode 160000 index 53c1f1c..0000000 --- a/c/SimpleDemo/godot_headers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 53c1f1c645161b60a4f33bc52686cc872fbf5770 diff --git a/c/SimpleDemo/src/simple.c b/c/SimpleDemo/src/simple.c deleted file mode 100644 index 451d51b..0000000 --- a/c/SimpleDemo/src/simple.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include -#include - -typedef struct user_data_struct { - char data[256]; -} user_data_struct; - -const godot_gdnative_core_api_struct *api = NULL; -const godot_gdnative_ext_nativescript_api_struct *nativescript_api = NULL; - -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); - -void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *p_options) { - api = p_options->api_struct; - - // now find our extensions - for (int i = 0; i < api->num_extensions; i++) { - switch (api->extensions[i]->type) { - case GDNATIVE_EXT_NATIVESCRIPT: { - nativescript_api = (godot_gdnative_ext_nativescript_api_struct *)api->extensions[i]; - }; break; - default: - break; - }; - }; -} - -void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *p_options) { - api = NULL; - nativescript_api = NULL; -} - -void GDN_EXPORT godot_nativescript_init(void *p_handle) { - godot_instance_create_func create = { NULL, NULL, NULL }; - create.create_func = &simple_constructor; - - godot_instance_destroy_func destroy = { NULL, NULL, NULL }; - destroy.destroy_func = &simple_destructor; - - nativescript_api->godot_nativescript_register_class(p_handle, "SIMPLE", "Reference", create, destroy); - - godot_instance_method get_data = { NULL, NULL, NULL }; - get_data.method = &simple_get_data; - - godot_method_attributes attributes = { GODOT_METHOD_RPC_MODE_DISABLED }; - - nativescript_api->godot_nativescript_register_method(p_handle, "SIMPLE", "get_data", attributes, get_data); -} - -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; -} - -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); -} - -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; - user_data_struct *user_data = (user_data_struct *)p_user_data; - - api->godot_string_new(&data); - api->godot_string_parse_utf8(&data, user_data->data); - api->godot_variant_new_string(&ret, &data); - api->godot_string_destroy(&data); - - return ret; -} diff --git a/c/SimpleDemo/README.md b/c/simple/README.md similarity index 72% rename from c/SimpleDemo/README.md rename to c/simple/README.md index c9b0081..c1a422b 100644 --- a/c/SimpleDemo/README.md +++ b/c/simple/README.md @@ -16,7 +16,7 @@ You can use scons to compile the library if you have it installed: scons platform=PLATFORM ``` -Where platform is: x11, osx or windows +Where platform is: windows, linuxbsd, or macos ### Linux To compile the library on Linux, do @@ -24,10 +24,10 @@ To compile the library on Linux, do ``` cd src clang -std=c11 -fPIC -c -I../godot_headers simple.c -o simple.os -clang -shared simple.os -o ../demo/bin/x11/libsimple.so +clang -shared simple.os -o ../project/gdnative/linuxbsd/libsimple.so ``` -This creates the file `libsimple.so` in your `demo/bin/x11` directory. +This creates the file `libsimple.so` in your `project/gdnative/linuxbsd` directory. For windows you need to find out what compiler flags need to be used, I don't know which ones. (If you do, feel free to fork and update this project and README) ### Mac OS X @@ -36,7 +36,7 @@ On Mac OS X: ``` cd src clang -std=c11 -fPIC -c -I../godot_headers simple.c -o simple.os -arch i386 -arch x86_64 -clang -dynamiclib simple.os -o ../demo/bin/osx/libsimple.dylib -arch i386 -arch x86_64 +clang -dynamiclib simple.os -o ../project/gdnative/macos/libsimple.dylib -arch i386 -arch x86_64 ``` This creates the file 'libsimple.dylib' as a universal binary (or alternatively remove one of the -arch options from both commands if you want to just compile for one architecture). @@ -47,10 +47,10 @@ On Windows: ``` cd src cl /Fosimple.obj /c simple.c /nologo -EHsc -DNDEBUG /MD /I. /I../godot_headers -link /nologo /dll /out:..\demo\bin\win64\libsimple.dll /implib:..\demo\bin\win64\libsimple.lib simple.obj +link /nologo /dll /out:..\project\gdnative\windows\libsimple.dll /implib:..\project\gdnative\windows\libsimple.lib simple.obj ``` -This creates the file `libsimple.dll` in your `demo/bin/win64` directory. +This creates the file `libsimple.dll` in your `project/gdnative/windows` directory. ## Usage diff --git a/c/SimpleDemo/SConstruct b/c/simple/SConstruct similarity index 58% rename from c/SimpleDemo/SConstruct rename to c/simple/SConstruct index 2d14720..babd99a 100644 --- a/c/SimpleDemo/SConstruct +++ b/c/simple/SConstruct @@ -3,41 +3,50 @@ import os, subprocess opts = Variables([], ARGUMENTS) -# Gets the standard flags CC, CCX, etc. -env = DefaultEnvironment() - -# Define our options -opts.Add(EnumVariable("target", "Compilation target", "debug", ["d", "debug", "r", "release"])) -opts.Add(EnumVariable("platform", "Compilation platform", "", ["", "windows", "x11", "linux", "osx"])) -opts.Add(EnumVariable("p", "Compilation target, alias for 'platform'", "", ["", "windows", "x11", "linux", "osx"])) -opts.Add(BoolVariable("use_llvm", "Use the LLVM / Clang compiler", "no")) -opts.Add(PathVariable("target_path", "The path where the lib is installed.", "demo/bin/")) -opts.Add(PathVariable("target_name", "The library name.", "libsimple", PathVariable.PathAccept)) - -# Local dependency paths, adapt them to your setup +# Define the relative path to the Godot headers. godot_headers_path = "godot_headers/" -# only support 64 at this time.. +# Gets the standard flags CC, CCX, etc. +env = DefaultEnvironment() +env["STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME"] = 1 + +# Define our options. Use future-proofed names for platforms. +platform_array = ["", "windows", "linuxbsd", "macos", "x11", "linux", "osx"] +opts.Add(EnumVariable("target", "Compilation target", "debug", ["d", "debug", "r", "release"])) +opts.Add(EnumVariable("platform", "Compilation platform", "", platform_array)) +opts.Add(EnumVariable("p", "Alias for 'platform'", "", platform_array)) +opts.Add(BoolVariable("use_llvm", "Use the LLVM / Clang compiler", "no")) +opts.Add(PathVariable("target_path", "The path where the lib is installed.", "project/gdnative/")) +opts.Add(PathVariable("target_name", "The library name.", "libsimple", PathVariable.PathAccept)) + +# Only support 64-bit systems. bits = 64 # Updates the environment with the option variables. opts.Update(env) -# Process some arguments -if env["use_llvm"]: - env["CC"] = "clang" - env["CXX"] = "clang++" - +# Process platform arguments. if env["p"] != "": env["platform"] = env["p"] +if env["platform"] == "osx": + env["platform"] = "macos" +elif env["platform"] in ("x11", "linux"): + env["platform"] = "linuxbsd" + if env["platform"] == "": print("No valid target platform selected.") quit() +env["target_path"] += env["platform"] + "/" + +# Process other arguments. +if env["use_llvm"]: + env["CC"] = "clang" + env["CXX"] = "clang++" + # Check our platform specifics -if env["platform"] == "osx": - env["target_path"] += "osx/" +if env["platform"] == "macos": if env["target"] in ("debug", "d"): env.Append(CCFLAGS=["-g", "-O2", "-arch", "x86_64"]) env.Append(LINKFLAGS=["-arch", "x86_64"]) @@ -45,17 +54,16 @@ if env["platform"] == "osx": env.Append(CCFLAGS=["-g", "-O3", "-arch", "x86_64"]) env.Append(LINKFLAGS=["-arch", "x86_64"]) -elif env["platform"] in ("x11", "linux"): - env["target_path"] += "x11/" +elif env["platform"] == "linuxbsd": if env["target"] in ("debug", "d"): - env.Append(CCFLAGS=["-fPIC", "-g3", "-Og", "-std=c++17"]) + env.Append(CCFLAGS=["-fPIC", "-g3", "-Og"]) else: - env.Append(CCFLAGS=["-fPIC", "-g", "-O3", "-std=c++17"]) + env.Append(CCFLAGS=["-fPIC", "-g", "-O3"]) elif env["platform"] == "windows": - env["target_path"] += "win64/" - # This makes sure to keep the session environment variables on windows, - # that way you can run scons in a vs 2017 prompt and it will find all the required tools + # This makes sure to keep the session environment variables + # on Windows, so that you can run scons in a VS 2017 prompt + # and it will find all the required tools. env.Append(ENV=os.environ) env.Append(CCFLAGS=["-DWIN32", "-D_WIN32", "-D_WINDOWS", "-W3", "-GR", "-D_CRT_SECURE_NO_WARNINGS"]) @@ -64,10 +72,15 @@ elif env["platform"] == "windows": else: env.Append(CCFLAGS=["-O2", "-EHsc", "-DNDEBUG", "-MD"]) -# make sure our binding library is properly includes +# Make sure our library includes the Godot headers. env.Append(CPPPATH=[".", godot_headers_path]) -# tweak this if you want to use different folders, or more folders, to store your source code in. +# Make sure our library looks in the target path for any other +# libraries it may need. The path needs to be project-relative. +env.Append(LINKFLAGS=["-Wl,-rpath,gdnative/" + env["platform"]]) + +# Tweak this if you want to use different folders, +# or more folders, to store your source code in. env.Append(CPPPATH=["src/"]) sources = Glob("src/*.c") diff --git a/c/simple/godot_headers b/c/simple/godot_headers new file mode 160000 index 0000000..f212219 --- /dev/null +++ b/c/simple/godot_headers @@ -0,0 +1 @@ +Subproject commit f2122198d51f230d903f9585527248f6cf411494 diff --git a/c/SimpleDemo/demo/bin/osx/.gitignore b/c/simple/project/gdnative/linuxbsd/.gitignore similarity index 100% rename from c/SimpleDemo/demo/bin/osx/.gitignore rename to c/simple/project/gdnative/linuxbsd/.gitignore diff --git a/c/SimpleDemo/demo/bin/win64/.gitignore b/c/simple/project/gdnative/macos/.gitignore similarity index 100% rename from c/SimpleDemo/demo/bin/win64/.gitignore rename to c/simple/project/gdnative/macos/.gitignore diff --git a/c/simple/project/gdnative/simple.gdnlib b/c/simple/project/gdnative/simple.gdnlib new file mode 100644 index 0000000..71ad8f4 --- /dev/null +++ b/c/simple/project/gdnative/simple.gdnlib @@ -0,0 +1,18 @@ +[general] + +singleton=false +load_once=true +symbol_prefix="godot_" +reloadable=true + +[entry] + +OSX.64="res://gdnative/macos/libsimple.dylib" +Windows.64="res://gdnative/windows/libsimple.dll" +X11.64="res://gdnative/linuxbsd/libsimple.so" + +[dependencies] + +OSX.64=[ ] +Windows.64=[ ] +X11.64=[ ] diff --git a/c/SimpleDemo/demo/bin/simple.gdns b/c/simple/project/gdnative/simple.gdns similarity index 69% rename from c/SimpleDemo/demo/bin/simple.gdns rename to c/simple/project/gdnative/simple.gdns index 4bb9e31..a6b3cfd 100644 --- a/c/SimpleDemo/demo/bin/simple.gdns +++ b/c/simple/project/gdnative/simple.gdns @@ -1,6 +1,6 @@ [gd_resource type="NativeScript" load_steps=2 format=2] -[ext_resource path="res://bin/simple.gdnlib" type="GDNativeLibrary" id=1] +[ext_resource path="res://gdnative/simple.gdnlib" type="GDNativeLibrary" id=1] [resource] diff --git a/c/SimpleDemo/demo/bin/x11/.gitignore b/c/simple/project/gdnative/windows/.gitignore similarity index 100% rename from c/SimpleDemo/demo/bin/x11/.gitignore rename to c/simple/project/gdnative/windows/.gitignore diff --git a/c/SimpleDemo/demo/icon.png b/c/simple/project/icon.png similarity index 100% rename from c/SimpleDemo/demo/icon.png rename to c/simple/project/icon.png diff --git a/c/simple/project/icon.png.import b/c/simple/project/icon.png.import new file mode 100644 index 0000000..96cbf46 --- /dev/null +++ b/c/simple/project/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.png" +dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/c/SimpleDemo/demo/main.gd b/c/simple/project/main.gd similarity index 73% rename from c/SimpleDemo/demo/main.gd rename to c/simple/project/main.gd index ca80a5f..6f702f8 100644 --- a/c/SimpleDemo/demo/main.gd +++ b/c/simple/project/main.gd @@ -1,7 +1,7 @@ extends Control # load the SIMPLE library -const SIMPLE = preload("res://bin/simple.gdns") +const SIMPLE = preload("res://gdnative/simple.gdns") onready var data = SIMPLE.new() func _on_Button_pressed(): diff --git a/c/SimpleDemo/demo/main.tscn b/c/simple/project/main.tscn similarity index 99% rename from c/SimpleDemo/demo/main.tscn rename to c/simple/project/main.tscn index c5bf9cb..9382cfb 100644 --- a/c/SimpleDemo/demo/main.tscn +++ b/c/simple/project/main.tscn @@ -20,5 +20,4 @@ margin_top = 311.0 margin_right = 629.0 margin_bottom = 368.0 size_flags_vertical = 0 - [connection signal="pressed" from="Button" to="." method="_on_Button_pressed"] diff --git a/c/SimpleDemo/demo/project.godot b/c/simple/project/project.godot similarity index 74% rename from c/SimpleDemo/demo/project.godot rename to c/simple/project/project.godot index b661c6b..a43f6a0 100644 --- a/c/SimpleDemo/demo/project.godot +++ b/c/simple/project/project.godot @@ -15,12 +15,9 @@ _global_script_class_icons={ [application] -config/name="SimpleDemo" +config/name="Simple GDNative Demo" run/main_scene="res://main.tscn" config/icon="res://icon.png" -name="SimpleDemo" -main_scene="res://main.tscn" -icon="res://icon.png" [gdnative] @@ -29,7 +26,3 @@ singletons=[ ] [memory] multithread/thread_rid_pool_prealloc=60 - -[rendering] - -viewport/default_environment="res://default_env.tres" diff --git a/c/simple/src/simple.c b/c/simple/src/simple.c new file mode 100644 index 0000000..1561b27 --- /dev/null +++ b/c/simple/src/simple.c @@ -0,0 +1,115 @@ +#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; + + // Find NativeScript extensions. + for (int i = 0; i < api->num_extensions; i++) { + switch (api->extensions[i]->type) { + case GDNATIVE_EXT_NATIVESCRIPT: { + nativescript_api = (godot_gdnative_ext_nativescript_api_struct *)api->extensions[i]; + }; break; + default: + break; + }; + }; +} + +// `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; + + 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 }; + get_data.method = &simple_get_data; + + 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) { + 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) { + 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; + user_data_struct *user_data = (user_data_struct *)p_user_data; + + api->godot_string_new(&data); + api->godot_string_parse_utf8(&data, user_data->data); + api->godot_variant_new_string(&ret, &data); + api->godot_string_destroy(&data); + + return ret; +}