gdextension_c_example.rst 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167
  1. .. _doc_gdextension_c_example:
  2. GDExtension C example
  3. =====================
  4. Introduction
  5. ------------
  6. This is a simple example on how to work with GDExtension directly with C code.
  7. Note that the API is not meant to be used directly, so this will definitely be
  8. quite verbose and require a lot of steps even for a small example. However, it
  9. serves as a reference for creating bindings for a different language. It is
  10. still possible to use the API directly if you prefer, which might be convenient
  11. when only binding a third-party library.
  12. In this example we will create a custom node that moves a sprite on the screen
  13. based on the user's parameters. While very simple, it serves to show how to do
  14. some of the things with GDExtension, like registering custom classes with
  15. methods, properties, and signals. It gives an insight on the GDExtension API.
  16. Setting up the project
  17. ----------------------
  18. There are a few prerequisites you'll need:
  19. - a Godot 4.2 (or later) executable,
  20. - a C compiler,
  21. - SCons as a build tool.
  22. Since this is using the API directly, there's no need to use the
  23. `godot-cpp repository <https://github.com/godotengine/godot-cpp>`__.
  24. File structure
  25. --------------
  26. To organize our files, we're gonna split into mainly two folders:
  27. .. code-block:: none
  28. gdextension_c_example/
  29. |
  30. +--demo/ # game example/demo to test the extension
  31. |
  32. +--src/ # source code of the extension we are building
  33. We also need a copy of the ``gdextension_interface.h`` header from the Godot
  34. source code, which can be obtained directly from the Godot executable by running
  35. the following command:
  36. .. code-block:: none
  37. godot --dump-gdextension-interface
  38. This creates the header in the current folder, so you can just copy it to the ``src``
  39. folder in the example project.
  40. Lastly, there's another source of information we need to refer to, which is the JSON
  41. file with the Godot API reference. This file won't be used by the code directly, we
  42. will only use it to extract some information manually.
  43. To get this JSON file, just call the Godot executable:
  44. .. code-block:: none
  45. godot --dump-extension-api
  46. The resulting ``extension_api.json`` file will be created in the current
  47. folder. You can copy this file to the example folder to have it handy.
  48. .. note::
  49. This extension is targeting Godot 4.2, but it should work on later versions as
  50. well. If you want to target a different minimal version, make sure to get the
  51. header and the JSON from the version Godot version you are targeting.
  52. Buildsystem
  53. -----------
  54. Using a buildsystem makes our life a lot easier when dealing with C code. For
  55. the sake of convenience, we'll use SCons since it's the same as what Godot
  56. itself uses.
  57. The following ``SConstruct`` file is a simple one that will build your extension
  58. to the current platform that you are using, be it Linux, macOS, or Windows. This
  59. will be a non-optimized build for debugging purposes. It also assumes a 64-bit
  60. build, which is relevant for some parts of the example code. Making other build
  61. types and cross-compilation is out of the scope of this tutorial. Save this file
  62. to the root folder.
  63. .. code-block:: python
  64. #!/bin/env python
  65. from SCons.Script import Environment
  66. from os import path
  67. import sys
  68. env = Environment()
  69. # Set the target path and name.
  70. target_path = "demo/bin/"
  71. target_name = "libgdexample"
  72. # Set the compiler and flags.
  73. env.Append(CPPPATH=["src"]) # Add the src folder to the include path.
  74. env.Append(CFLAGS=["-O0", "-g"]) # Make it a debug build.
  75. # Use Clang on macOS.
  76. if sys.platform == "darwin":
  77. env["CC"] = "clang"
  78. # Add all C files in "src" folder as sources.
  79. sources = env.Glob("src/*.c")
  80. # Create a shared library.
  81. library = env.SharedLibrary(
  82. target=path.join(target_path, target_name),
  83. source=sources,
  84. )
  85. # Set the library as the default target.
  86. env.Default(library)
  87. This will include all C files in the ``src`` folder, so we don't need to change
  88. this file when adding new source files.
  89. Initializing the extension
  90. --------------------------
  91. The first bit of code will be responsible for initializing the extension. This is
  92. what makes Godot aware of what our GDExtension provides, such as classes and
  93. plugins.
  94. Create the file ``init.h`` in the ``src`` folder, with the following contents:
  95. .. code-block:: c
  96. #ifndef INIT_H
  97. #define INIT_H
  98. #include "defs.h"
  99. #include "gdextension_interface.h"
  100. void initialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level);
  101. void deinitialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level);
  102. GDExtensionBool GDE_EXPORT gdexample_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
  103. #endif // INIT_H
  104. The functions declared here have the signatures expected by the GDExtension API.
  105. Note the inclusion of the ``defs.h`` file. This is one of our helpers to
  106. simplify writing the extension code. For now it will only contain the definition
  107. of ``GDE_EXPORT``, a macro that makes the function public in the shared library
  108. so Godot can properly call it. This macro helps abstracting what each compiler
  109. expects.
  110. Create the ``defs.h`` file in the ``src`` folder with the following contents:
  111. .. code-block:: c
  112. #ifndef DEFS_H
  113. #define DEFS_H
  114. #include <stdbool.h>
  115. #include <stddef.h>
  116. #include <stdint.h>
  117. #if !defined(GDE_EXPORT)
  118. #if defined(_WIN32)
  119. #define GDE_EXPORT __declspec(dllexport)
  120. #elif defined(__GNUC__)
  121. #define GDE_EXPORT __attribute__((visibility("default")))
  122. #else
  123. #define GDE_EXPORT
  124. #endif
  125. #endif // ! GDE_EXPORT
  126. #endif // DEFS_H
  127. We also include some standard headers to make things easier. Now we only have to
  128. include ``defs.h`` and those will come as a bonus.
  129. Now, let's implement the functions we just declared. Create a file called
  130. ``init.c`` in the ``src`` folder and add this code:
  131. .. code-block:: c
  132. #include "init.h"
  133. void initialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level)
  134. {
  135. }
  136. void deinitialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level)
  137. {
  138. }
  139. GDExtensionBool GDE_EXPORT gdexample_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
  140. {
  141. r_initialization->initialize = initialize_gdexample_module;
  142. r_initialization->deinitialize = deinitialize_gdexample_module;
  143. r_initialization->userdata = NULL;
  144. r_initialization->minimum_initialization_level = GDEXTENSION_INITIALIZATION_SCENE;
  145. return true;
  146. }
  147. What this does is set up the initialization data that Godot expects. The
  148. functions to initialize and deinitialize are set so Godot will call then when
  149. needed. It also sets the initialization level which varies per extension. Since
  150. we plan to add a custom node, the ``SCENE`` level is enough.
  151. We will fill the ``initialize_gdexample_module()`` function later to register our custom class.
  152. A basic class
  153. -------------
  154. In order to make an actual node, first we'll create a C struct to hold data and
  155. functions that will act as methods. The plan is to make this a custom node that
  156. inherits from :ref:`Sprite2D <class_Sprite2D>`.
  157. Create a file called ``gdexample.h`` in the ``src`` folder with the following
  158. contents:
  159. .. code-block:: c
  160. #ifndef GDEXAMPLE_H
  161. #define GDEXAMPLE_H
  162. #include "gdextension_interface.h"
  163. #include "defs.h"
  164. // Struct to hold the node data.
  165. typedef struct
  166. {
  167. // Metadata.
  168. GDExtensionObjectPtr object; // Stores the underlying Godot object.
  169. } GDExample;
  170. // Constructor for the node.
  171. void gdexample_class_constructor(GDExample *self);
  172. // Destructor for the node.
  173. void gdexample_class_destructor(GDExample *self);
  174. // Bindings.
  175. void gdexample_class_bind_methods();
  176. #endif // GDEXAMPLE_H
  177. Noteworthy here is the ``object`` field, which holds a pointer to
  178. the Godot object, and the ``gdexample_class_bind_methods()`` function, which will
  179. register the metadata of our custom class (properties, methods, and signals).
  180. The latter is not entirely necessary, as we can do it when registering the
  181. class, but it makes clearer to separate the concerns and let our class register
  182. its own metadata.
  183. The ``object`` field is necessary because our class will inherit a Godot class.
  184. Since we can't inherit it directly, as we are not interacting with the source
  185. code (and C doesn't even have classes), we instead tell Godot to create an
  186. object of a type it knows and attach our extension to it. We will need the
  187. reference to such objects when calling methods on the parent class, for
  188. instance.
  189. Let's create the source counterpart of this header. Create the file
  190. ``gdexample.c`` in the ``src`` folder and add the following code to it:
  191. .. code-block:: c
  192. #include "gdexample.h"
  193. void gdexample_class_constructor(GDExample *self)
  194. {
  195. }
  196. void gdexample_class_destructor(GDExample *self)
  197. {
  198. }
  199. void gdexample_class_bind_methods()
  200. {
  201. }
  202. As we don't have anything to do with those functions yet, they'll stay empty
  203. for a while.
  204. The next step is registering our class. However, in order to do so we need to
  205. create a :ref:`StringName <class_StringName>` and for that we have to get a
  206. function from the GDExtension API. Since we'll need this a few times and we'll
  207. also need other things, let's create a wrapper API to facilitate this kind of
  208. chore.
  209. A wrapper API
  210. -------------
  211. We'll start by creating an ``api.h`` file in the ``src`` folder:
  212. .. code-block:: c
  213. #ifndef API_H
  214. #define API_H
  215. /*
  216. This file works as a collection of helpers to call the GDExtension API
  217. in a less verbose way, as well as a cache for methods from the discovery API,
  218. just so we don't have to keep loading the same methods again.
  219. */
  220. #include "gdextension_interface.h"
  221. #include "defs.h"
  222. extern GDExtensionClassLibraryPtr class_library;
  223. // API methods.
  224. struct Constructors
  225. {
  226. GDExtensionInterfaceStringNameNewWithLatin1Chars string_name_new_with_latin1_chars;
  227. } constructors;
  228. struct Destructors
  229. {
  230. GDExtensionPtrDestructor string_name_destructor;
  231. } destructors;
  232. struct API
  233. {
  234. GDExtensionInterfaceClassdbRegisterExtensionClass2 classdb_register_extension_class2;
  235. } api;
  236. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address);
  237. #endif // API_H
  238. This file will include many other helpers as we fill our extension with
  239. something useful. For now it only has a pointer to a function that creates a
  240. StringName from a C string (in Latin-1 encoding) and another to destruct a
  241. StringName, which we'll need to use to avoid leaking memory, as well as the
  242. function to register a class, which is our initial goal.
  243. We also keep a reference to the ``class_library`` here. This is something that
  244. Godot provides to us when initializing the extension and we'll need to use it
  245. when registering the things we create so Godot can tell which extension is
  246. making the call.
  247. There's also a function to load those function pointers from the GDExtension API.
  248. Let's work on the source counterpart of this header. Create the ``api.c`` file
  249. in the ``src`` folder, adding the following code:
  250. .. code-block:: c
  251. #include "api.h"
  252. GDExtensionClassLibraryPtr class_library = NULL;
  253. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  254. {
  255. // Get helper functions first.
  256. GDExtensionInterfaceVariantGetPtrDestructor variant_get_ptr_destructor = (GDExtensionInterfaceVariantGetPtrDestructor)p_get_proc_address("variant_get_ptr_destructor");
  257. // API.
  258. api.classdb_register_extension_class2 = p_get_proc_address("classdb_register_extension_class2");
  259. // Constructors.
  260. constructors.string_name_new_with_latin1_chars = p_get_proc_address("string_name_new_with_latin1_chars");
  261. // Destructors.
  262. destructors.string_name_destructor = variant_get_ptr_destructor(GDEXTENSION_VARIANT_TYPE_STRING_NAME);
  263. }
  264. The first important thing here is ``p_get_proc_address``. This a function from
  265. the GDExtension API that is passed during initialization. You can use this
  266. function to request specific functions from the API by their name. Here we are
  267. caching the results so we don't have to keep a reference for
  268. ``p_get_proc_address`` everywhere and use our wrapper instead.
  269. At the start we request the ``variant_get_ptr_destructor()`` function. This is not
  270. going to be used outside of this function, so we don't add to our wrapper and
  271. only cache it locally. The cast is necessary to silence compiler warnings.
  272. Then we get the function that creates a StringName from a C string, exactly what
  273. we mentioned before as a needed function. We store that in our ``constructors``
  274. struct.
  275. Next, we use the ``variant_get_ptr_destructor()`` function we just got to query
  276. for the destructor for StringName, using the enum value from
  277. ``gdextension_interface.h`` API as a parameter. We could get destructors for
  278. other types in a similar manner, but we'll limit ourselves to what is needed for
  279. the example.
  280. Lastly, we get the ``classdb_register_extension_class2()`` function, which we'll
  281. need in order to register our custom class.
  282. .. note::
  283. You may wonder why the ``2`` is there in the function name. This means it's the
  284. second version of this function. The old version is kept to ensure backwards
  285. compatibility with older extensions, but since we have the second version
  286. available, it's best to use the new one, because we don't intend to support older
  287. Godot versions in this example.
  288. The ``gdextension_interface.h`` header documents in which Godot version each
  289. function was introduced.
  290. We also define the ``class_library`` variable here, which will be set during
  291. initialization.
  292. Speaking of initialization, now we have to change the ``init.c`` file in
  293. order to fill the things we just added:
  294. .. code-block:: c
  295. GDExtensionBool GDE_EXPORT gdexample_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
  296. {
  297. class_library = p_library;
  298. load_api(p_get_proc_address);
  299. ...
  300. Here we set the ``class_library`` as needed and call our new ``load_api()``
  301. function. Don't forget to also include the new headers at the top of this file:
  302. .. code-block:: c
  303. #include "init.h"
  304. #include "api.h"
  305. #include "gdexample.h"
  306. ...
  307. Since we are here, we can register our new custom class. Let's fill the
  308. ``initialize_gdexample_module()`` function:
  309. .. code-block:: c
  310. void initialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level)
  311. {
  312. if (p_level != GDEXTENSION_INITIALIZATION_SCENE)
  313. {
  314. return;
  315. }
  316. // Register class.
  317. StringName class_name;
  318. constructors.string_name_new_with_latin1_chars(&class_name, "GDExample", false);
  319. StringName parent_class_name;
  320. constructors.string_name_new_with_latin1_chars(&parent_class_name, "Sprite2D", false);
  321. GDExtensionClassCreationInfo2 class_info = {
  322. .is_virtual = false,
  323. .is_abstract = false,
  324. .is_exposed = true,
  325. .set_func = NULL,
  326. .get_func = NULL,
  327. .get_property_list_func = NULL,
  328. .free_property_list_func = NULL,
  329. .property_can_revert_func = NULL,
  330. .property_get_revert_func = NULL,
  331. .validate_property_func = NULL,
  332. .notification_func = NULL,
  333. .to_string_func = NULL,
  334. .reference_func = NULL,
  335. .unreference_func = NULL,
  336. .create_instance_func = gdexample_class_create_instance,
  337. .free_instance_func = gdexample_class_free_instance,
  338. .recreate_instance_func = NULL,
  339. .get_virtual_func = NULL,
  340. .get_virtual_call_data_func = NULL,
  341. .call_virtual_with_data_func = NULL,
  342. .get_rid_func = NULL,
  343. .class_userdata = NULL,
  344. };
  345. api.classdb_register_extension_class2(class_library, &class_name, &parent_class_name, &class_info);
  346. // Bind methods.
  347. gdexample_class_bind_methods();
  348. // Destruct things.
  349. destructors.string_name_destructor(&class_name);
  350. destructors.string_name_destructor(&parent_class_name);
  351. }
  352. The struct with the class information is the biggest thing here. None of its
  353. fields are required with the exception of ``create_instance_func`` and
  354. ``free_instance_func``. We haven't made those functions yet, so we'll have
  355. to work on them soon. Note that we skip the initialization if it isn't at the
  356. ``SCENE`` level. This function may be called multiple times, once for each
  357. level, but we only want to register our class once.
  358. The other undefined thing here is ``StringName``. This will be an opaque struct
  359. meant to hold the data of a Godot StringName in our extension. We'll define it
  360. in the appropriately named ``defs.h`` file:
  361. .. code-block:: c
  362. ...
  363. // The sizes can be obtained from the extension_api.json file.
  364. #ifdef BUILD_32
  365. #define STRING_NAME_SIZE 4
  366. #else
  367. #define STRING_NAME_SIZE 8
  368. #endif
  369. // Types.
  370. typedef struct
  371. {
  372. uint8_t data[STRING_NAME_SIZE];
  373. } StringName;
  374. #endif // DEFS_H
  375. As mentioned in the comment, the sizes can be found in the
  376. ``extension_api.json`` file that we generated earlier, under the
  377. ``builtin_class_sizes`` property. The ``BUILD_32`` is never defined, as we
  378. assume we are working with a 64-bits build of Godot here, but if you need it you
  379. can add ``env.Append(CPPDEFINES=["BUILD_32"])`` to your ``SConstruct`` file.
  380. The ``// Types.`` comment foreshadows that we'll be adding more types to this
  381. file. Let's leave that for later.
  382. The ``StringName`` struct here is just to hold Godot data, so we don't really
  383. care what is inside of it. Though, in this case, it is just a pointer to the
  384. data in the heap. We'll use this struct when we need to allocate data for a
  385. StringName ourselves, like we are doing when registering our class.
  386. Back to registering, we need to work on our create and free functions. Let's
  387. include them in ``gdexample.h`` since they're specific to the custom class:
  388. .. code-block:: c
  389. ...
  390. // Bindings.
  391. void gdexample_class_bind_methods();
  392. GDExtensionObjectPtr gdexample_class_create_instance(void *p_class_userdata);
  393. void gdexample_class_free_instance(void *p_class_userdata, GDExtensionClassInstancePtr p_instance);
  394. ...
  395. Before we can implement those function, we'll need a few more things in our API.
  396. We need a way to allocate and free memory. While we could do this with good ol'
  397. ``malloc()``, we can instead make use of Godot's memory management functions.
  398. We'll also need a way to create a Godot object and set it with our custom
  399. instance.
  400. So let's change the ``api.h`` to include these new functions:
  401. .. code-block:: c
  402. ...
  403. struct API
  404. {
  405. GDExtensionInterfaceClassdbRegisterExtensionClass2 classdb_register_extension_class2;
  406. GDExtensionInterfaceClassdbConstructObject classdb_construct_object;
  407. GDExtensionInterfaceObjectSetInstance object_set_instance;
  408. GDExtensionInterfaceObjectSetInstanceBinding object_set_instance_binding;
  409. GDExtensionInterfaceMemAlloc mem_alloc;
  410. GDExtensionInterfaceMemFree mem_free;
  411. } api;
  412. Then we change the ``load_api()`` function in ``api.c`` to grab these new functions:
  413. .. code-block:: c
  414. ...
  415. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  416. {
  417. ...
  418. // API.
  419. api.classdb_register_extension_class2 = p_get_proc_address("classdb_register_extension_class2");
  420. api.classdb_construct_object = (GDExtensionInterfaceClassdbConstructObject)p_get_proc_address("classdb_construct_object");
  421. api.object_set_instance = p_get_proc_address("object_set_instance");
  422. api.object_set_instance_binding = p_get_proc_address("object_set_instance_binding");
  423. api.mem_alloc = (GDExtensionInterfaceMemAlloc)p_get_proc_address("mem_alloc");
  424. api.mem_free = (GDExtensionInterfaceMemFree)p_get_proc_address("mem_free");
  425. }
  426. Now we can go back to ``gdexample.c`` and define the new functions, without forgetting to
  427. include the ``api.h`` header:
  428. .. code-block:: c
  429. #include "gdexample.h"
  430. #include "api.h"
  431. ...
  432. const GDExtensionInstanceBindingCallbacks gdexample_class_binding_callbacks = {
  433. .create_callback = NULL,
  434. .free_callback = NULL,
  435. .reference_callback = NULL,
  436. };
  437. GDExtensionObjectPtr gdexample_class_create_instance(void *p_class_userdata)
  438. {
  439. // Create native Godot object;
  440. StringName class_name;
  441. constructors.string_name_new_with_latin1_chars(&class_name, "Sprite2D", false);
  442. GDExtensionObjectPtr object = api.classdb_construct_object(&class_name);
  443. destructors.string_name_destructor(&class_name);
  444. // Create extension object.
  445. GDExample *self = (GDExample *)api.mem_alloc(sizeof(GDExample));
  446. gdexample_class_constructor(self);
  447. self->object = object;
  448. // Set the extension instance in the native Godot object.
  449. constructors.string_name_new_with_latin1_chars(&class_name, "GDExample", false);
  450. api.object_set_instance(object, &class_name, self);
  451. api.object_set_instance_binding(object, class_library, self, &gdexample_class_binding_callbacks);
  452. destructors.string_name_destructor(&class_name);
  453. return object;
  454. }
  455. void gdexample_class_free_instance(void *p_class_userdata, GDExtensionClassInstancePtr p_instance)
  456. {
  457. if (p_instance == NULL)
  458. {
  459. return;
  460. }
  461. GDExample *self = (GDExample *)p_instance;
  462. gdexample_class_destructor(self);
  463. api.mem_free(self);
  464. }
  465. When instantiating an object, first we create a new Sprite2D object, since
  466. that's the parent of our class. Then we allocate memory for our custom struct
  467. and call its constructor. We save the pointer to the Godot object in the struct
  468. as well like we mentioned earlier.
  469. Then we set our custom struct as the instance data. This will make Godot know
  470. that the object is an instance of our custom class and properly call our custom
  471. methods for instance, as well as passing this data back.
  472. Note that we return the Godot object we created, not our custom struct.
  473. For the ``gdextension_free_instance()`` function, we only call the destructor and free the memory we
  474. allocated for the custom data. It is not necessary to destruct the Godot object
  475. since that will be taken care of by the engine itself.
  476. A demo project
  477. --------------
  478. Now that we can create and free our custom object, we should be able to try it
  479. out in an actual project. For this, you need to open Godot and create a new
  480. project on the ``demo`` folder. The project manager may warn you the folder
  481. isn't empty if you have compiled the extension before, you can safely ignore
  482. this warning this time.
  483. If you didn't compile the extension yet, it is the time to do it now. To do
  484. that, open a terminal or command prompt, navigate to the root folder of the
  485. extension and run ``scons``. It should compile quickly since the extension is
  486. very simple.
  487. Then, create a file called ``gdexample.gdextension`` inside the ``demo`` folder.
  488. This is a Godot resource that describes the extension, allowing the engine to
  489. properly load it. Put the following content in this file:
  490. .. code-block::
  491. [configuration]
  492. entry_symbol = "gdexample_library_init"
  493. compatibility_minimum = "4.2"
  494. [libraries]
  495. macos.debug = "res://bin/libgdexample.dylib"
  496. linux.debug = "res://bin/libgdexample.so"
  497. windows.debug = "res://bin/libgdexample.dll"
  498. As you can see, ``gdexample_library_init()`` is the same name of the function we
  499. defined in our ``init.c`` file. It is important that the names match because it
  500. is how Godot calls the entry point of the extension.
  501. We also set the compatibility minimum to 4.2, since we are targeting this
  502. version. It should still work on later versions. If you are using a later Godot
  503. version and rely on the new features, you need to increase this value to a
  504. version number that has everything you use.
  505. See :ref:`doc_what_is_gdextension_version_compatibility` for more information.
  506. In the ``[libraries]`` section we set up the paths to the shared library on
  507. different platforms. Here there's only the debug versions since that's what we
  508. are working on for the example. Using :ref:`feature tags <doc_feature_tags>` you
  509. can fine tune this to also provide release versions, add more target operating systems, as
  510. well as providing 32-bit and 64-bit binaries.
  511. You can also add library dependencies and custom icons for your classes in this
  512. file, but this is out of the scope for this tutorial.
  513. After saving the file, go back to the editor. Godot should automatically load
  514. the extension. Nothing will be seen because our extension only registers a new
  515. class. To use this class add a ``Node2D`` as a root of the scene. Move it to
  516. the middle of viewport for better visibility. Then add a new child node to the
  517. root and in the **Create New Node** dialog search for "GDExample", the name of
  518. our class, as it should be listed there. If it isn't, it means that Godot didn't
  519. load the extension properly, so try restarting the editor and retrace the steps
  520. to see if anything went missing.
  521. Our custom class is derived from ``Sprite2D``, so it has a **Texture** property
  522. in the Inspector. Set this to the ``icon.svg`` file that Godot handily created
  523. for us when making the project. Save this scene as ``main.tscn`` and run it. You
  524. may want to set it as the main scene for convenience.
  525. .. image:: img/gdextension_c_running.webp
  526. Voilà! We have a custom node running in Godot. However, it does not do anything
  527. and has nothing different than a regular ``Sprite2D`` node. We will fix that next by
  528. adding custom methods and properties.
  529. Custom methods
  530. --------------
  531. A common thing in extensions is creating methods for the custom classes and
  532. exposing those to the Godot API. We are going to create a couple of getters and
  533. setters which are need for binding the properties afterwards.
  534. First, let's add the new fields in our struct to hold the values for
  535. ``amplitude`` and ``speed``, which we will use later on when creating the
  536. behavior for the node. Add them to the ``gdexample.h`` file, changing the
  537. ``GDExample`` struct:
  538. .. code-block:: c
  539. ...
  540. typedef struct
  541. {
  542. // Public properties.
  543. double amplitude;
  544. double speed;
  545. // Metadata.
  546. GDExtensionObjectPtr object; // Stores the underlying Godot object.
  547. } GDExample;
  548. ...
  549. In the same file, add the declaration for the getters and setters, right after
  550. the destructor.
  551. .. code-block:: c
  552. ...
  553. // Destructor for the node.
  554. void gdexample_class_destructor(GDExample *self);
  555. // Properties.
  556. void gdexample_class_set_amplitude(GDExample *self, double amplitude);
  557. double gdexample_class_get_amplitude(const GDExample *self);
  558. void gdexample_class_set_speed(GDExample *self, double speed);
  559. double gdexample_class_get_speed(const GDExample *self);
  560. ...
  561. In the ``gdexample.cpp`` file, we will initialize these values in the constructor
  562. and add the implementations for those new functions, which are quite trivial:
  563. .. code-block:: c
  564. void gdexample_class_constructor(GDExample *self)
  565. {
  566. self->amplitude = 10.0;
  567. self->speed = 1.0;
  568. }
  569. void gdexample_class_set_amplitude(GDExample *self, double amplitude)
  570. {
  571. self->amplitude = amplitude;
  572. }
  573. double gdexample_class_get_amplitude(const GDExample *self)
  574. {
  575. return self->amplitude;
  576. }
  577. void gdexample_class_set_speed(GDExample *self, double speed)
  578. {
  579. self->speed = speed;
  580. }
  581. double gdexample_class_get_speed(const GDExample *self)
  582. {
  583. return self->speed;
  584. }
  585. To make those simple functions work when called by Godot, we will need some
  586. wrappers to help us properly convert the data to and from the engine.
  587. First, we will create wrappers for ``ptrcall``. This is what Godot uses when the
  588. types of the values are known to be exact, which avoids using Variant. We're
  589. gonna need two of those: one for the functions that take no arguments and
  590. return a ``double`` (for the getters) and another for the functions that take a
  591. single ``double`` argument and return nothing (for the setters).
  592. Add the declarations to the ``api.h`` file:
  593. .. code-block:: c
  594. void ptrcall_0_args_ret_float(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
  595. void ptrcall_1_float_arg_no_ret(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
  596. Those two functions follow the ``GDExtensionClassMethodPtrCall`` type, as
  597. defined in the ``gdextension_interface.h``. We use ``float`` as a name here
  598. because in Godot the ``float`` type has double precision, so we keep this
  599. convention.
  600. Then we implement those functions in the ``api.c`` file:
  601. .. code-block:: c
  602. void ptrcall_0_args_ret_float(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret)
  603. {
  604. // Call the function.
  605. double (*function)(void *) = method_userdata;
  606. *((double *)r_ret) = function(p_instance);
  607. }
  608. void ptrcall_1_float_arg_no_ret(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret)
  609. {
  610. // Call the function.
  611. void (*function)(void *, double) = method_userdata;
  612. function(p_instance, *((double *)p_args[0]));
  613. }
  614. The ``method_userdata`` argument is a custom value that we give to Godot, in
  615. this case we will set as the function pointer for the one we want to call. So
  616. first we convert it to the function type, then we just call it by passing the
  617. arguments when needed, or setting the return value.
  618. The ``p_instance`` argument contains the custom instance of our class, which we
  619. gave with ``object_set_instance()`` when creating the object.
  620. ``p_args`` is an array of arguments. Note this contains **pointers** to the
  621. values. That's why we dereference it when passing to our functions. The number
  622. of arguments will be declared when binding the function (which we will do soon)
  623. and it will always include default ones if those exist.
  624. Finally, the ``r_ret`` is a pointer to the variable where the return value needs to
  625. be set. Like the arguments, it will be the correct type as declared. For the
  626. function that does not return, we have to avoid setting it.
  627. Note how the type and argument counts are exact, so if we needed different
  628. types, for example, we would have to create more wrappers. This could be
  629. automated using some code generation, but this is out of the scope for this
  630. tutorial.
  631. While the ``ptrcall`` functions are used when types are exact, sometimes Godot cannot know
  632. if that's the case (when the call comes from a dynamically typed language, such
  633. as GDScript). In those situations it uses regular ``call`` functions, so we need to
  634. provide those as well when binding.
  635. Let's create two new wrappers in the ``api.h`` file:
  636. .. code-block:: c
  637. void call_0_args_ret_float(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
  638. void call_1_float_arg_no_ret(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
  639. These follow the ``GDExtensionClassMethodCall`` type, which is a bit different.
  640. First, you receive pointers to Variants instead of exact types. There's also the
  641. amount of arguments and an error struct that you can set if something goes
  642. wrong.
  643. In order to check the type and also extract interact with Variant, we will need
  644. a few more functions from the GDExtension API. So let's expand our wrapper
  645. structs:
  646. .. code-block:: c
  647. struct Constructors {
  648. ...
  649. GDExtensionVariantFromTypeConstructorFunc variant_from_float_constructor;
  650. GDExtensionTypeFromVariantConstructorFunc float_from_variant_constructor;
  651. } constructors;
  652. struct API
  653. {
  654. ...
  655. GDExtensionInterfaceGetVariantFromTypeConstructor get_variant_from_type_constructor;
  656. GDExtensionInterfaceGetVariantToTypeConstructor get_variant_to_type_constructor;
  657. GDExtensionInterfaceVariantGetType variant_get_type;
  658. } api;
  659. The names say all about what those do. We have a couple of constructors to
  660. create and extract a floating point value to and from a Variant. We also have a
  661. couple of helpers to actually get those constructors, as well as a function to
  662. find out the type of a Variant.
  663. Let's get those from the API, like we did before, by changing the ``load_api()``
  664. function in the ``api.c`` file:
  665. .. code-block:: c
  666. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  667. {
  668. ...
  669. // API.
  670. ...
  671. api.get_variant_from_type_constructor = (GDExtensionInterfaceGetVariantFromTypeConstructor)p_get_proc_address("get_variant_from_type_constructor");
  672. api.get_variant_to_type_constructor = (GDExtensionInterfaceGetVariantToTypeConstructor)p_get_proc_address("get_variant_to_type_constructor");
  673. api.variant_get_type = (GDExtensionInterfaceVariantGetType)p_get_proc_address("variant_get_type");
  674. ...
  675. // Constructors.
  676. ...
  677. constructors.variant_from_float_constructor = api.get_variant_from_type_constructor(GDEXTENSION_VARIANT_TYPE_FLOAT);
  678. constructors.float_from_variant_constructor = api.get_variant_to_type_constructor(GDEXTENSION_VARIANT_TYPE_FLOAT);
  679. ...
  680. }
  681. Now that we have these set, we can implement our call wrappers in the same file:
  682. .. code-block:: c
  683. void call_0_args_ret_float(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error)
  684. {
  685. // Check argument count.
  686. if (p_argument_count != 0)
  687. {
  688. r_error->error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  689. r_error->expected = 0;
  690. return;
  691. }
  692. // Call the function.
  693. double (*function)(void *) = method_userdata;
  694. double result = function(p_instance);
  695. // Set resulting Variant.
  696. constructors.variant_from_float_constructor(r_return, &result);
  697. }
  698. void call_1_float_arg_no_ret(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error)
  699. {
  700. // Check argument count.
  701. if (p_argument_count < 1)
  702. {
  703. r_error->error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
  704. r_error->expected = 1;
  705. return;
  706. }
  707. else if (p_argument_count > 1)
  708. {
  709. r_error->error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
  710. r_error->expected = 1;
  711. return;
  712. }
  713. // Check the argument type.
  714. GDExtensionVariantType type = api.variant_get_type(p_args[0]);
  715. if (type != GDEXTENSION_VARIANT_TYPE_FLOAT)
  716. {
  717. r_error->error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT;
  718. r_error->expected = GDEXTENSION_VARIANT_TYPE_FLOAT;
  719. r_error->argument = 0;
  720. return;
  721. }
  722. // Extract the argument.
  723. double arg1;
  724. constructors.float_from_variant_constructor(&arg1, (GDExtensionVariantPtr)p_args[0]);
  725. // Call the function.
  726. void (*function)(void *, double) = method_userdata;
  727. function(p_instance, arg1);
  728. }
  729. These functions are a bit longer but easy to follow. First they check if the
  730. argument count is as expected and if not they set the error struct and
  731. return. For the one that has one parameter, it also checks if the argument type
  732. is correct. This is important because mismatched types when extracting from
  733. Variant can cause crashes.
  734. Then it proceeds to extract the argument using the constructor we setup before.
  735. The one with no arguments instead sets the return value after calling the
  736. function. Note how they use a pointer to a ``double`` variable, since this is
  737. what those constructors expect.
  738. Before we can actually bind our methods, we need a way to create
  739. ``GDExtensionPropertyInfo`` instances. While we could do them inside the binding
  740. functions that we'll implement afterwards, it's easier to have a helper for it
  741. since we'll need it multiple times, including for when we bind properties.
  742. Let's create these two functions in the ``api.h`` file:
  743. .. code-block:: c
  744. // Create a PropertyInfo struct.
  745. GDExtensionPropertyInfo make_property(
  746. GDExtensionVariantType type,
  747. const char *name);
  748. GDExtensionPropertyInfo make_property_full(
  749. GDExtensionVariantType type,
  750. const char *name,
  751. uint32_t hint,
  752. const char *hint_string,
  753. const char *class_name,
  754. uint32_t usage_flags);
  755. void destruct_property(GDExtensionPropertyInfo *info);
  756. The first one is a simplified version of the second since we usually don't need
  757. all the arguments for the property and are okay with the defaults. Then we also
  758. have a function to destruct the PropertyInfo since we need to create Strings and
  759. StringNames that need to be properly disposed of.
  760. Speaking of which, we also need a way to create and destruct Strings, so we'll
  761. make an addition to existing structs in this same file. We'll also get a new API
  762. function for actually binding our custom method.
  763. .. code-block:: c
  764. struct Constructors
  765. {
  766. ...
  767. GDExtensionInterfaceStringNewWithUtf8Chars string_new_with_utf8_chars;
  768. } constructors;
  769. struct Destructors
  770. {
  771. ...
  772. GDExtensionPtrDestructor string_destructor;
  773. } destructors;
  774. struct API
  775. {
  776. ...
  777. GDExtensionInterfaceClassdbRegisterExtensionClassMethod classdb_register_extension_class_method;
  778. } api;
  779. Before implementing those, let's do a quick stop in the ``defs.h`` file and
  780. include the size of the ``String`` type and a couple of enums:
  781. .. code-block:: c
  782. // The sizes can be obtained from the extension_api.json file.
  783. #ifdef BUILD_32
  784. #define STRING_SIZE 4
  785. #define STRING_NAME_SIZE 4
  786. #else
  787. #define STRING_SIZE 8
  788. #define STRING_NAME_SIZE 8
  789. #endif
  790. ...
  791. typedef struct
  792. {
  793. uint8_t data[STRING_SIZE];
  794. } String;
  795. // Enums.
  796. typedef enum
  797. {
  798. PROPERTY_HINT_NONE = 0,
  799. } PropertyHint;
  800. typedef enum
  801. {
  802. PROPERTY_USAGE_NONE = 0,
  803. PROPERTY_USAGE_STORAGE = 2,
  804. PROPERTY_USAGE_EDITOR = 4,
  805. PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR,
  806. } PropertyUsageFlags;
  807. While it's the same size as ``StringName``, it is more clear to use a different
  808. name for it.
  809. The enums here are just helpers to give names to the numbers they represent. The
  810. information about them is present in the ``extension_api.json`` file. Here we
  811. just set up the ones we need for the tutorial, to keep it more concise.
  812. Going now to the ``api.c``, we need to load the pointers to the new functions we
  813. added to the API.
  814. .. code-block:: c
  815. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  816. {
  817. ...
  818. // API
  819. ...
  820. api.classdb_register_extension_class_method = p_get_proc_address("classdb_register_extension_class_method");
  821. // Constructors.
  822. ...
  823. constructors.string_new_with_utf8_chars = p_get_proc_address("string_new_with_utf8_chars");
  824. // Destructors.
  825. ...
  826. destructors.string_destructor = variant_get_ptr_destructor(GDEXTENSION_VARIANT_TYPE_STRING);
  827. }
  828. Then we can also implement the functions to create the ``PropertyInfo`` struct.
  829. .. code-block:: c
  830. GDExtensionPropertyInfo make_property(
  831. GDExtensionVariantType type,
  832. const char *name)
  833. {
  834. return make_property_full(type, name, PROPERTY_HINT_NONE, "", "", PROPERTY_USAGE_DEFAULT);
  835. }
  836. GDExtensionPropertyInfo make_property_full(
  837. GDExtensionVariantType type,
  838. const char *name,
  839. uint32_t hint,
  840. const char *hint_string,
  841. const char *class_name,
  842. uint32_t usage_flags)
  843. {
  844. StringName *prop_name = api.mem_alloc(sizeof(StringName));
  845. constructors.string_name_new_with_latin1_chars(prop_name, name, false);
  846. String *prop_hint_string = api.mem_alloc(sizeof(String));
  847. constructors.string_new_with_utf8_chars(prop_hint_string, hint_string);
  848. StringName *prop_class_name = api.mem_alloc(sizeof(StringName));
  849. constructors.string_name_new_with_latin1_chars(prop_class_name, class_name, false);
  850. GDExtensionPropertyInfo info = {
  851. .name = prop_name,
  852. .type = type,
  853. .hint = hint,
  854. .hint_string = prop_hint_string,
  855. .class_name = prop_class_name,
  856. .usage = usage_flags,
  857. };
  858. return info;
  859. }
  860. void destruct_property(GDExtensionPropertyInfo *info)
  861. {
  862. destructors.string_name_destructor(info->name);
  863. destructors.string_destructor(info->hint_string);
  864. destructors.string_name_destructor(info->class_name);
  865. api.mem_free(info->name);
  866. api.mem_free(info->hint_string);
  867. api.mem_free(info->class_name);
  868. }
  869. The simple version of ``make_property()`` just calls the more complete one with a
  870. some default arguments. What those values mean exactly is out of the scope of
  871. this tutorial, check the page about the :ref:`Object class <doc_object_class>`
  872. for more details about binding methods and properties.
  873. The complete version is more involved. First, it creates ``String``'s and
  874. ``StringName``'s for the needed fields, by allocating memory and calling their
  875. constructors. Then it creates a ``GDExtensionPropertyInfo`` struct and sets all
  876. the fields with the arguments provided. Finally it returns this created struct.
  877. The ``destruct_property()`` function is straightforward, it simply calls the
  878. destructors for the created objects and frees their allocated memory.
  879. Let's go back again to the header ``api.h`` to create the functions that will
  880. actually bind the methods:
  881. .. code-block:: c
  882. // Version for 0 arguments, with return.
  883. void bind_method_0_r(
  884. const char *class_name,
  885. const char *method_name,
  886. void *function,
  887. GDExtensionVariantType return_type);
  888. // Version for 1 argument, no return.
  889. void bind_method_1(
  890. const char *class_name,
  891. const char *method_name,
  892. void *function,
  893. const char *arg1_name,
  894. GDExtensionVariantType arg1_type);
  895. Then switch back to the ``api.c`` file to implement these:
  896. .. code-block:: c
  897. // Version for 0 arguments, with return.
  898. void bind_method_0_r(
  899. const char *class_name,
  900. const char *method_name,
  901. void *function,
  902. GDExtensionVariantType return_type)
  903. {
  904. StringName method_name_string;
  905. constructors.string_name_new_with_latin1_chars(&method_name_string, method_name, false);
  906. GDExtensionClassMethodCall call_func = call_0_args_ret_float;
  907. GDExtensionClassMethodPtrCall ptrcall_func = ptrcall_0_args_ret_float;
  908. GDExtensionPropertyInfo return_info = make_property(return_type, "");
  909. GDExtensionClassMethodInfo method_info = {
  910. .name = &method_name_string,
  911. .method_userdata = function,
  912. .call_func = call_func,
  913. .ptrcall_func = ptrcall_func,
  914. .method_flags = GDEXTENSION_METHOD_FLAGS_DEFAULT,
  915. .has_return_value = true,
  916. .return_value_info = &return_info,
  917. .return_value_metadata = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE,
  918. .argument_count = 0,
  919. };
  920. StringName class_name_string;
  921. constructors.string_name_new_with_latin1_chars(&class_name_string, class_name, false);
  922. api.classdb_register_extension_class_method(class_library, &class_name_string, &method_info);
  923. // Destruct things.
  924. destructors.string_name_destructor(&method_name_string);
  925. destructors.string_name_destructor(&class_name_string);
  926. destruct_property(&return_info);
  927. }
  928. // Version for 1 argument, no return.
  929. void bind_method_1(
  930. const char *class_name,
  931. const char *method_name,
  932. void *function,
  933. const char *arg1_name,
  934. GDExtensionVariantType arg1_type)
  935. {
  936. StringName method_name_string;
  937. constructors.string_name_new_with_latin1_chars(&method_name_string, method_name, false);
  938. GDExtensionClassMethodCall call_func = call_1_float_arg_no_ret;
  939. GDExtensionClassMethodPtrCall ptrcall_func = ptrcall_1_float_arg_no_ret;
  940. GDExtensionPropertyInfo args_info[] = {
  941. make_property(arg1_type, arg1_name),
  942. };
  943. GDExtensionClassMethodArgumentMetadata args_metadata[] = {
  944. GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE,
  945. };
  946. GDExtensionClassMethodInfo method_info = {
  947. .name = &method_name_string,
  948. .method_userdata = function,
  949. .call_func = call_func,
  950. .ptrcall_func = ptrcall_func,
  951. .method_flags = GDEXTENSION_METHOD_FLAGS_DEFAULT,
  952. .has_return_value = false,
  953. .argument_count = 1,
  954. .arguments_info = args_info,
  955. .arguments_metadata = args_metadata,
  956. };
  957. StringName class_name_string;
  958. constructors.string_name_new_with_latin1_chars(&class_name_string, class_name, false);
  959. api.classdb_register_extension_class_method(class_library, &class_name_string, &method_info);
  960. // Destruct things.
  961. destructors.string_name_destructor(&method_name_string);
  962. destructors.string_name_destructor(&class_name_string);
  963. destruct_property(&args_info[0]);
  964. }
  965. Both functions are very similar. First, they create a ``StringName`` with the
  966. method name. This is created in the stack since we don't need to keep it after
  967. the function ends. Then they create local variables to hold the ``call_func``
  968. and ``ptrcall_func``, pointing to the helper functions we defined earlier.
  969. In the next step they diverge a bit. The first one creates a property for the
  970. return value, which has an empty name since it's not needed. The other creates
  971. an array of properties for the arguments, which in this case has a single
  972. element. This one also has an array of metadata, which can be used if there's
  973. something special about the argument (e.g. if an ``int`` value is 32 bits long
  974. instead of the default of 64 bits).
  975. Afterwards, they create the ``GDExtensionClassMethodInfo`` with the required
  976. fields for each case. Then they make a ``StringName`` for the class name, in
  977. order to associate the method with the class. Next, they call the API function
  978. to actually bind this method to the class. Finally, we destruct the objects we
  979. created since they aren't needed anymore.
  980. .. note::
  981. The bind helpers here use the call helpers we created earlier, so do note that
  982. those call helpers only accept the Godot ``FLOAT`` type (which is equivalent to
  983. ``double`` in C). If you intend to use this for other types, you would need to
  984. check the type of the arguments and return type and select an appropriate
  985. function callback. This is avoided here only to keep the example from becoming
  986. even longer.
  987. Now that we have the means to bind methods, we can actually do so in our custom
  988. class. Go to the ``gdexample.c`` file and fill up the
  989. ``gdexample_class_bind_methods()`` function:
  990. .. code-block:: c
  991. void gdexample_class_bind_methods()
  992. {
  993. bind_method_0_r("GDExample", "get_amplitude", gdexample_class_get_amplitude, GDEXTENSION_VARIANT_TYPE_FLOAT);
  994. bind_method_1("GDExample", "set_amplitude", gdexample_class_set_amplitude, "amplitude", GDEXTENSION_VARIANT_TYPE_FLOAT);
  995. bind_method_0_r("GDExample", "get_speed", gdexample_class_get_speed, GDEXTENSION_VARIANT_TYPE_FLOAT);
  996. bind_method_1("GDExample", "set_speed", gdexample_class_set_speed, "speed", GDEXTENSION_VARIANT_TYPE_FLOAT);
  997. }
  998. Since this function is already being called by the initialization process, we
  999. can stop here. This function is much more straightforward after we created all the
  1000. infrastructure to make this work. You can see that implementing the binding
  1001. functions inline here would take some space and also be quite repetitive. This
  1002. also makes it easier to add another method in the future.
  1003. If you compile the code and reopen the demo project, nothing will be different
  1004. at first, since we only added two new methods. To ensure those are registered
  1005. properly, you can search for ``GDExample`` in the editor help and verify they
  1006. are present in the documentation page.
  1007. .. image:: img/gdextension_c_methods_doc.webp
  1008. Custom properties
  1009. -----------------
  1010. Since we now have the getter and setter for our properties already bound, we can
  1011. move forward to create actual properties that will be displayed in the Godot
  1012. editor inspector.
  1013. Given our extensive setup in the previous section, there are only a few things
  1014. needed to enable us to bind properties. First, let's get a new API function in
  1015. the ``api.h`` file:
  1016. .. code-block:: c
  1017. struct API {
  1018. ...
  1019. GDExtensionInterfaceClassdbRegisterExtensionClassProperty classdb_register_extension_class_property;
  1020. } api;
  1021. Let's also declare a function here to bind properties:
  1022. .. code-block:: c
  1023. void bind_property(
  1024. const char *class_name,
  1025. const char *name,
  1026. GDExtensionVariantType type,
  1027. const char *getter,
  1028. const char *setter);
  1029. In the ``api.c`` file, we can load the new API function:
  1030. .. code-block:: c
  1031. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  1032. {
  1033. // API
  1034. ...
  1035. api.classdb_register_extension_class_property = p_get_proc_address("classdb_register_extension_class_property");
  1036. ...
  1037. }
  1038. Then we can implement our new helper function in this same file:
  1039. .. code-block:: c
  1040. void bind_property(
  1041. const char *class_name,
  1042. const char *name,
  1043. GDExtensionVariantType type,
  1044. const char *getter,
  1045. const char *setter)
  1046. {
  1047. StringName class_string_name;
  1048. constructors.string_name_new_with_latin1_chars(&class_string_name, class_name, false);
  1049. GDExtensionPropertyInfo info = make_property(type, name);
  1050. StringName getter_name;
  1051. constructors.string_name_new_with_latin1_chars(&getter_name, getter, false);
  1052. StringName setter_name;
  1053. constructors.string_name_new_with_latin1_chars(&setter_name, setter, false);
  1054. api.classdb_register_extension_class_property(class_library, &class_string_name, &info, &setter_name, &getter_name);
  1055. // Destruct things.
  1056. destructors.string_name_destructor(&class_string_name);
  1057. destruct_property(&info);
  1058. destructors.string_name_destructor(&getter_name);
  1059. destructors.string_name_destructor(&setter_name);
  1060. }
  1061. This function is similar to the one for binding methods. The main difference is
  1062. that we don't need an extra struct since we can simply use the
  1063. ``GDExtensionPropertyInfo`` that is created by our helper function, so it's more
  1064. straightforward. It only creates the ``StringName`` values from the
  1065. C strings, creates a property info struct using our helper, calls the API
  1066. function to register the property in the class and then destructs all the objects
  1067. we created.
  1068. With this done, we can extend the ``gdexample_class_bind_methods()`` function in the
  1069. ``gdexample.c`` file:
  1070. .. code-block:: c
  1071. void gdexample_class_bind_methods()
  1072. {
  1073. bind_method_0_r("GDExample", "get_amplitude", gdexample_class_get_amplitude, GDEXTENSION_VARIANT_TYPE_FLOAT);
  1074. bind_method_1("GDExample", "set_amplitude", gdexample_class_set_amplitude, "amplitude", GDEXTENSION_VARIANT_TYPE_FLOAT);
  1075. bind_property("GDExample", "amplitude", GDEXTENSION_VARIANT_TYPE_FLOAT, "get_amplitude", "set_amplitude");
  1076. bind_method_0_r("GDExample", "get_speed", gdexample_class_get_speed, GDEXTENSION_VARIANT_TYPE_FLOAT);
  1077. bind_method_1("GDExample", "set_speed", gdexample_class_set_speed, "speed", GDEXTENSION_VARIANT_TYPE_FLOAT);
  1078. bind_property("GDExample", "speed", GDEXTENSION_VARIANT_TYPE_FLOAT, "get_speed", "set_speed");
  1079. }
  1080. If you build the extension with ``scons``, you'll see in the Godot editor the new property shown
  1081. not only on the documentation page for the custom class but also in the Inspector dock when the
  1082. ``GDExample`` node is selected.
  1083. .. image:: img/gdextension_c_inspector_properties.webp
  1084. Binding virtual methods
  1085. -----------------------
  1086. Our custom node now has properties to influence how it operates, but it still
  1087. doesn't do anything. In this section, we will bind the virtual method
  1088. :ref:`_process() <class_Node_private_method__process>` and make our custom sprite
  1089. move a little bit.
  1090. In the ``gdexample.h`` file, let's add a function that represents the custom
  1091. ``_process()`` method:
  1092. .. code-block:: c
  1093. // Methods.
  1094. void gdexample_class_process(GDExample *self, double delta);
  1095. We'll also add a "private" field to keep track of the time passed in our custom
  1096. struct. This is "private" only in the sense that it won't be bound to the Godot
  1097. API, even though it is public in the C side, given the language lacks access
  1098. modifiers.
  1099. .. code-block:: c
  1100. typedef struct
  1101. {
  1102. // Private properties.
  1103. double time_passed;
  1104. ...
  1105. } GDExample;
  1106. On the counterpart source file ``gdexample.c`` we need to initialize the new
  1107. field in the constructor:
  1108. .. code-block:: c
  1109. void gdexample_class_constructor(GDExample *self)
  1110. {
  1111. self->time_passed = 0.0;
  1112. self->amplitude = 10.0;
  1113. self->speed = 1.0;
  1114. }
  1115. Then we can create the simplest implementation for the ``_process`` method:
  1116. .. code-block:: c
  1117. void gdexample_class_process(GDExample *self, double delta)
  1118. {
  1119. self->time_passed += self->speed * delta;
  1120. }
  1121. For now it will do nothing but update the private field we created. We'll come
  1122. back to this after the method is properly bound.
  1123. Virtual methods are a bit different from the regular bindings. Instead of
  1124. explicitly registering the method itself, we'll register a special function that
  1125. Godot will call to ask if a particular virtual method is implemented in our
  1126. extension. The engine will pass a ``StringName`` as an argument so, following
  1127. the spirit of this tutorial, we'll create a helper function to check if it is
  1128. equal to a C string.
  1129. Let's add the declaration to the ``api.h`` file:
  1130. .. code-block:: c
  1131. // Compare a StringName with a C string.
  1132. bool is_string_name_equal(GDExtensionConstStringNamePtr p_a, const char *p_b);
  1133. We'll also add a new struct to this file, to hold function pointers for custom operators:
  1134. .. code-block:: c
  1135. struct Operators
  1136. {
  1137. GDExtensionPtrOperatorEvaluator string_name_equal;
  1138. } operators;
  1139. Then in the ``api.c`` file we'll load the function pointer from the API:
  1140. .. code-block:: c
  1141. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  1142. {
  1143. // Get helper functions first.
  1144. ...
  1145. GDExtensionInterfaceVariantGetPtrOperatorEvaluator variant_get_ptr_operator_evaluator = (GDExtensionInterfaceVariantGetPtrOperatorEvaluator)p_get_proc_address("variant_get_ptr_operator_evaluator");
  1146. ...
  1147. // Operators.
  1148. operators.string_name_equal = variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_EQUAL, GDEXTENSION_VARIANT_TYPE_STRING_NAME, GDEXTENSION_VARIANT_TYPE_STRING_NAME);
  1149. }
  1150. As you can see we need a new local helper here in order to grab the function
  1151. pointer for the operator.
  1152. With this handy, we can easily create our comparison function in the same file:
  1153. .. code-block:: c
  1154. bool is_string_name_equal(GDExtensionConstStringNamePtr p_a, const char *p_b)
  1155. {
  1156. // Create a StringName for the C string.
  1157. StringName string_name;
  1158. constructors.string_name_new_with_latin1_chars(&string_name, p_b, false);
  1159. // Compare both StringNames.
  1160. bool is_equal = false;
  1161. operators.string_name_equal(p_a, &string_name, &is_equal);
  1162. // Destroy the created StringName.
  1163. destructors.string_name_destructor(&string_name);
  1164. // Return the result.
  1165. return is_equal;
  1166. }
  1167. This function creates a ``StringName`` from the argument, compares with
  1168. the other one using the operator function pointer, and returns the result. Note
  1169. that the return value for the operator is passed as an out reference, this is a
  1170. common thing in the API.
  1171. Let's go back to the ``gdexample.h`` file and add a couple of functions that
  1172. will be used as the callbacks for the Godot API:
  1173. .. code-block:: c
  1174. void *gdexample_class_get_virtual_with_data(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
  1175. void gdexample_class_call_virtual_with_data(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, void *p_virtual_call_userdata, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
  1176. There are actually two ways of registering virtual methods. Only one has the
  1177. ``get`` part, in which you give Godot a properly crafted function pointer which
  1178. will be called. For this we would need to create another helper for each virtual
  1179. method, something that is not very convenient. Instead, we use the second method
  1180. which allows us to return any data, and then Godot will call a second callback
  1181. and give us back this data along with the call information. We can simply give
  1182. our own function pointer as custom data and then have a single callback for all
  1183. virtual methods. Although in this example we will only use it for one method,
  1184. this way is simpler to expand.
  1185. So let's implement those two functions in the ``gdexample.c`` file:
  1186. .. code-block:: c
  1187. void *gdexample_class_get_virtual_with_data(void *p_class_userdata, GDExtensionConstStringNamePtr p_name)
  1188. {
  1189. // If it is the "_process" method, return a pointer to the gdexample_class_process function.
  1190. if (is_string_name_equal(p_name, "_process"))
  1191. {
  1192. return (void *)gdexample_class_process;
  1193. }
  1194. // Otherwise, return NULL.
  1195. return NULL;
  1196. }
  1197. void gdexample_class_call_virtual_with_data(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, void *p_virtual_call_userdata, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret)
  1198. {
  1199. // If it is the "_process" method, call it with a helper.
  1200. if (p_virtual_call_userdata == &gdexample_class_process)
  1201. {
  1202. ptrcall_1_float_arg_no_ret(p_virtual_call_userdata, p_instance, p_args, r_ret);
  1203. }
  1204. }
  1205. Those functions are also quite straightforward after making all the helpers
  1206. previously.
  1207. For the first one, we simply check if the function name requested is
  1208. ``_process`` and if it is we return a function pointer to our implementation of
  1209. it. Otherwise we return ``NULL``, signaling that the method is not being
  1210. overridden. We don't use the ``p_class_userdata`` here since this function is
  1211. meant only for one class and we don't have any data associated with it.
  1212. The second one is similar. If it is the ``_process()`` method, it uses the given
  1213. function pointer to call the ``ptrcall`` helper, passing the call arguments
  1214. forward. Otherwise it simply does nothing, since we don't have any other virtual
  1215. methods being implemented.
  1216. The only thing missing is using those callbacks when the class is registered. Go
  1217. to the ``init.c`` file and change the ``class_info`` initialization to include
  1218. those, replacing the ``NULL`` value used previously:
  1219. .. code-block:: c
  1220. void initialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level)
  1221. {
  1222. ...
  1223. GDExtensionClassCreationInfo2 class_info = {
  1224. ...
  1225. .get_virtual_call_data_func = gdexample_class_get_virtual_with_data,
  1226. .call_virtual_with_data_func = gdexample_class_call_virtual_with_data,
  1227. ...
  1228. };
  1229. ...
  1230. }
  1231. This is enough to bind the virtual method. If you build the extension and run
  1232. the demo project again, the ``_process()`` function will be called. You just won't
  1233. be able to tell since the function itself does nothing visible. We will solve
  1234. this now by making the custom node move following a pattern.
  1235. In order to make our node do stuff, we'll need to call Godot methods. Not only
  1236. the GDExtension API functions as we've being doing so far, but actual engine
  1237. methods, as we would do with scripting. This naturally requires some extra setup.
  1238. First, let's add :ref:`class_Vector2` to our ``defs.h`` file, so we
  1239. can use it in our method:
  1240. .. code-block:: c
  1241. // The sizes can be obtained from the extension_api.json file.
  1242. ...
  1243. #ifdef REAL_T_IS_DOUBLE
  1244. #define VECTOR2_SIZE 16
  1245. #else
  1246. #define VECTOR2_SIZE 8
  1247. #endif
  1248. ...
  1249. // Types.
  1250. ...
  1251. typedef struct
  1252. {
  1253. uint8_t data[VECTOR2_SIZE];
  1254. } Vector2;
  1255. The ``REAL_T_IS_DOUBLE`` define is only needed if your Godot version was built
  1256. with double precision support, which is not the default.
  1257. Now, in the ``api.h`` file, we'll add few things to the API structs, including a
  1258. new one for holding engine methods to call.
  1259. .. code-block:: c
  1260. struct Constructors
  1261. {
  1262. ...
  1263. GDExtensionPtrConstructor vector2_constructor_x_y;
  1264. } constructors;
  1265. ...
  1266. struct Methods
  1267. {
  1268. GDExtensionMethodBindPtr node2d_set_position;
  1269. } methods;
  1270. struct API
  1271. {
  1272. ...
  1273. GDExtensionInterfaceClassdbGetMethodBind classdb_get_method_bind;
  1274. GDExtensionInterfaceObjectMethodBindPtrcall object_method_bind_ptrcall;
  1275. } api;
  1276. Then in the ``api.c`` file we can grab the function pointers from Godot:
  1277. .. code-block::
  1278. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  1279. {
  1280. // Get helper functions first.
  1281. ...
  1282. GDExtensionInterfaceVariantGetPtrConstructor variant_get_ptr_constructor = (GDExtensionInterfaceVariantGetPtrConstructor)p_get_proc_address("variant_get_ptr_constructor");
  1283. // API.
  1284. ...
  1285. api.classdb_get_method_bind = (GDExtensionInterfaceClassdbGetMethodBind)p_get_proc_address("classdb_get_method_bind");
  1286. api.object_method_bind_ptrcall = p_get_proc_address("object_method_bind_ptrcall");
  1287. // Constructors.
  1288. ...
  1289. constructors.vector2_constructor_x_y = variant_get_ptr_constructor(GDEXTENSION_VARIANT_TYPE_VECTOR2, 3); // See extension_api.json for indices.
  1290. ...
  1291. }
  1292. The only noteworthy part here is the ``Vector2`` constructor, for which we request the
  1293. index ``3``. Since there are multiple constructors with different kinds of
  1294. arguments, we need to specify which one we want. In this case we're getting the
  1295. one that takes two float numbers as the ``x`` and ``y`` coordinates, hence the
  1296. name. This index can be retrieved from the ``extension_api.json`` file. Note we
  1297. also need a new local helper to get it.
  1298. Be aware that we don't get anything for the methods struct here. This is because
  1299. this function is called too early in the initialization process, so classes
  1300. won't be properly registered yet.
  1301. Instead, we're gonna use the initialization level callback to grab those when we
  1302. are registering our custom class. Add this to the ``init.c`` file:
  1303. .. code-block:: c
  1304. void initialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level)
  1305. {
  1306. if (p_level != GDEXTENSION_INITIALIZATION_SCENE)
  1307. {
  1308. return;
  1309. }
  1310. // Get ClassDB methods here because the classes we need are all properly registered now.
  1311. // See extension_api.json for hashes.
  1312. StringName native_class_name;
  1313. StringName method_name;
  1314. constructors.string_name_new_with_latin1_chars(&native_class_name, "Node2D", false);
  1315. constructors.string_name_new_with_latin1_chars(&method_name, "set_position", false);
  1316. methods.node2d_set_position = api.classdb_get_method_bind(&native_class_name, &method_name, 743155724);
  1317. destructors.string_name_destructor(&native_class_name);
  1318. destructors.string_name_destructor(&method_name);
  1319. ...
  1320. }
  1321. Here we create ``StringName``'s for the class and method we want to get, then use
  1322. the GDExtension API to retrieve their ``MethodBind``, which is an object that
  1323. represents the bound method. We get the ``set_position`` method from ``Node2D``
  1324. since this is where it was registered, even though we're going to use it in a
  1325. ``Sprite2D``, a derived class.
  1326. The seemingly random number for getting the bind is actually a hash of the
  1327. method signature. This allows Godot to match the method you're requesting even
  1328. if in a future Godot version this signature changes, by providing a
  1329. compatibility method that matches what you're asking for. This is one of the
  1330. systems that allow the engine to load extensions made for previous versions. You
  1331. can get the value of this hash from the ``extension_api.json`` file.
  1332. With all that, we can finally implement our custom ``_process()`` method in the
  1333. ``gdexample.c`` file:
  1334. .. code-block:: c
  1335. ...
  1336. #include <math.h>
  1337. ...
  1338. void gdexample_class_process(GDExample *self, double delta)
  1339. {
  1340. self->time_passed += self->speed * delta;
  1341. Vector2 new_position;
  1342. // Set up the arguments for the Vector2 constructor.
  1343. double x = self->amplitude + (self->amplitude * sin(self->time_passed * 2.0));
  1344. double y = self->amplitude + (self->amplitude * cos(self->time_passed * 1.5));
  1345. GDExtensionConstTypePtr args[] = {&x, &y};
  1346. // Call the Vector2 constructor.
  1347. constructors.vector2_constructor_x_y(&new_position, args);
  1348. // Set up the arguments for the set_position method.
  1349. GDExtensionConstTypePtr args2[] = {&new_position};
  1350. // Call the set_position method.
  1351. api.object_method_bind_ptrcall(methods.node2d_set_position, self->object, args2, NULL);
  1352. }
  1353. After updating the time passed scaled by the ``speed`` property, it creates
  1354. ``x`` and ``y`` values based on that, also modulated by the ``amplitude``
  1355. property. This is what will give the pattern effect. The ``math.h`` header is
  1356. needed for the ``sin()`` and ``cos()`` functions used here.
  1357. Then it sets up an array of arguments to construct a ``Vector2``, followed by
  1358. calling the constructor. It sets up another array of arguments and use it to
  1359. call the ``set_position()`` method via the bind we acquired previously.
  1360. Since nothing here allocates any memory, there's not a need to cleanup.
  1361. Now we can build the extension again and reopen Godot. Even in the editor you'll
  1362. see the custom sprite moving.
  1363. .. image:: img/gdextension_c_moving_sprite.gif
  1364. Try changing the **Speed** and **Amplitude** properties and see how the sprite
  1365. react.
  1366. Registering and emitting a signal
  1367. ---------------------------------
  1368. To complete this tutorial, let's see how you can register a custom signal and
  1369. emit it when appropriate. As you might have guessed, we'll need a few more
  1370. function pointers from the API and more helper functions.
  1371. In the ``api.h`` file we're adding two things. One is a an API function to
  1372. register a signal, the other is a helper function to wrap the signal binding.
  1373. .. code-block:: c
  1374. struct API
  1375. {
  1376. ...
  1377. GDExtensionInterfaceClassdbRegisterExtensionClassSignal classdb_register_extension_class_signal;
  1378. } api;
  1379. ...
  1380. // Version for 1 argument.
  1381. void bind_signal_1(
  1382. const char *class_name,
  1383. const char *signal_name,
  1384. const char *arg1_name,
  1385. GDExtensionVariantType arg1_type);
  1386. In this case we only have a version for one argument, since it's what we're
  1387. going to use.
  1388. Moving to the ``api.c`` file, we can load this new function pointer and
  1389. implement the helper:
  1390. .. code-block:: c
  1391. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  1392. {
  1393. // API.
  1394. ...
  1395. api.classdb_register_extension_class_signal = p_get_proc_address("classdb_register_extension_class_signal");
  1396. ...
  1397. }
  1398. void bind_signal_1(
  1399. const char *class_name,
  1400. const char *signal_name,
  1401. const char *arg1_name,
  1402. GDExtensionVariantType arg1_type)
  1403. {
  1404. StringName class_string_name;
  1405. constructors.string_name_new_with_latin1_chars(&class_string_name, class_name, false);
  1406. StringName signal_string_name;
  1407. constructors.string_name_new_with_latin1_chars(&signal_string_name, signal_name, false);
  1408. GDExtensionPropertyInfo args_info[] = {
  1409. make_property(arg1_type, arg1_name),
  1410. };
  1411. api.classdb_register_extension_class_signal(class_library, &class_string_name, &signal_string_name, args_info, 1);
  1412. // Destruct things.
  1413. destructors.string_name_destructor(&class_string_name);
  1414. destructors.string_name_destructor(&signal_string_name);
  1415. destruct_property(&args_info[0]);
  1416. }
  1417. This one is very similar to the function to bind methods. The main difference is
  1418. that we don't need to fill another struct, we just pass the needed names and the
  1419. array of arguments. The ``1`` at the end means the amount of arguments the
  1420. signal provides.
  1421. With this we can bind the signal in ``gdexample.c``:
  1422. .. code-block:: c
  1423. void gdexample_class_bind_methods()
  1424. {
  1425. ...
  1426. bind_signal_1("GDExample", "position_changed", "new_position", GDEXTENSION_VARIANT_TYPE_VECTOR2);
  1427. }
  1428. In order to emit a signal, we need to call the
  1429. :ref:`emit_signal() <class_Object_method_emit_signal>` method on our custom node.
  1430. Since this is a ``vararg`` function (meaning it takes any amount of arguments),
  1431. we cannot use ``ptrcall``. To do a regular call, we have to create Variants,
  1432. which require a few more steps of plumbing to get done.
  1433. First, in the ``defs.h`` file we create a definition for Variant:
  1434. .. code-block:: c
  1435. ...
  1436. // The sizes can be obtained from the extension_api.json file.
  1437. ...
  1438. #ifdef REAL_T_IS_DOUBLE
  1439. #define VARIANT_SIZE 40
  1440. #define VECTOR2_SIZE 16
  1441. #else
  1442. #define VARIANT_SIZE 24
  1443. #define VECTOR2_SIZE 8
  1444. #endif
  1445. ...
  1446. // Types.
  1447. ...
  1448. typedef struct
  1449. {
  1450. uint8_t data[VARIANT_SIZE];
  1451. } Variant;
  1452. We first set the size of Variant together with the size of Vector2 that we added
  1453. before. Then we use it to create an opaque struct that is enough to hold the
  1454. Variant data. Again, we set the size for double precision builds as a fallback,
  1455. since by the official Godot builds use single precision.
  1456. The ``emit_signal()`` function will be called with two arguments. The first is
  1457. the name of the signal to be emitted and the second is the argument we're
  1458. passing to the signal connections, which is a Vector2 as we declared when
  1459. binding it. So we're gonna create a helper function that can call a MethodBind
  1460. with these types. Even though it does return something (an error code), we don't
  1461. need to deal with it, so for now we're just going to ignore it.
  1462. In the ``api.h``, we're adding a few things to the existing structs, plus a new
  1463. helper function for the call:
  1464. .. code-block:: c
  1465. struct Constructors
  1466. {
  1467. ...
  1468. GDExtensionVariantFromTypeConstructorFunc variant_from_string_name_constructor;
  1469. GDExtensionVariantFromTypeConstructorFunc variant_from_vector2_constructor;
  1470. } constructors;
  1471. struct Destructors
  1472. {
  1473. ..
  1474. GDExtensionInterfaceVariantDestroy variant_destroy;
  1475. } destructors;
  1476. ...
  1477. struct Methods
  1478. {
  1479. ...
  1480. GDExtensionMethodBindPtr object_emit_signal;
  1481. } methods;
  1482. struct API
  1483. {
  1484. ...
  1485. GDExtensionInterfaceObjectMethodBindCall object_method_bind_call;
  1486. } api;
  1487. ...
  1488. // Helper to call with Variant arguments.
  1489. void call_2_args_stringname_vector2_no_ret_variant(
  1490. GDExtensionMethodBindPtr p_method_bind,
  1491. GDExtensionObjectPtr p_instance,
  1492. const GDExtensionTypePtr p_arg1,
  1493. const GDExtensionTypePtr p_arg2);
  1494. Now let's switch to the ``api.c`` file to load these new function pointers and
  1495. implement the helper function.
  1496. .. code-block:: c
  1497. void load_api(GDExtensionInterfaceGetProcAddress p_get_proc_address)
  1498. {
  1499. // API.
  1500. ...
  1501. api.object_method_bind_call = p_get_proc_address("object_method_bind_call");
  1502. // Constructors.
  1503. ...
  1504. constructors.variant_from_string_name_constructor = api.get_variant_from_type_constructor(GDEXTENSION_VARIANT_TYPE_STRING_NAME);
  1505. constructors.variant_from_vector2_constructor = api.get_variant_from_type_constructor(GDEXTENSION_VARIANT_TYPE_VECTOR2);
  1506. // Destructors.
  1507. ...
  1508. destructors.variant_destroy = p_get_proc_address("variant_destroy");
  1509. ...
  1510. }
  1511. ...
  1512. void call_2_args_stringname_vector2_no_ret_variant(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionTypePtr p_arg1, const GDExtensionTypePtr p_arg2)
  1513. {
  1514. // Set up the arguments for the call.
  1515. Variant arg1;
  1516. constructors.variant_from_string_name_constructor(&arg1, p_arg1);
  1517. Variant arg2;
  1518. constructors.variant_from_vector2_constructor(&arg2, p_arg2);
  1519. GDExtensionConstVariantPtr args[] = {&arg1, &arg2};
  1520. // Add dummy return value storage.
  1521. Variant ret;
  1522. // Call the function.
  1523. api.object_method_bind_call(p_method_bind, p_instance, args, 2, &ret, NULL);
  1524. // Destroy the arguments that need it.
  1525. destructors.variant_destroy(&arg1);
  1526. destructors.variant_destroy(&ret);
  1527. }
  1528. This helper function has some boilerplate code but is quite straightforward. It sets up the
  1529. two arguments inside stack allocated Variants, then creates an array with
  1530. pointers to those. It also sets up another Variant to keep the return value,
  1531. which we don't need to construct since the call expects it to be uninitialized.
  1532. Then it actually calls the MethodBind using the instance we provided and the
  1533. arguments. The ``NULL`` at the end would be a pointer to a
  1534. ``GDExtensionCallError`` struct. This can be used to treat potential errors when
  1535. calling the functions (such as wrong arguments). For the sake of simplicity
  1536. we're not gonna handle that here.
  1537. At the end we need to destruct the Variants we created. While technically the
  1538. Vector2 one does not require destructing, it is clearer to cleanup everything.
  1539. We also need to load the MethodBind, which we'll do in the ``init.c`` file,
  1540. right after loading the one for the ``set_position`` method we did before:
  1541. .. code-block:: c
  1542. void initialize_gdexample_module(void *p_userdata, GDExtensionInitializationLevel p_level)
  1543. {
  1544. ...
  1545. constructors.string_name_new_with_latin1_chars(&native_class_name, "Object", false);
  1546. constructors.string_name_new_with_latin1_chars(&method_name, "emit_signal", false);
  1547. methods.object_emit_signal = api.classdb_get_method_bind(&native_class_name, &method_name, 4047867050);
  1548. destructors.string_name_destructor(&native_class_name);
  1549. destructors.string_name_destructor(&method_name);
  1550. // Register class.
  1551. ...
  1552. }
  1553. Note that we reuse the ``native_class_name`` and ``method_name`` variables here,
  1554. so we don't need to declare new ones.
  1555. Now go to the ``gdexample.h`` file where we're going to add a couple of fields:
  1556. .. code-block:: c
  1557. typedef struct
  1558. {
  1559. // Private properties.
  1560. ..
  1561. double time_emit;
  1562. ..
  1563. // Metadata.
  1564. StringName position_changed; // For signal.
  1565. } GDExample;
  1566. The first one will store the time passed since the last signal was emitted,
  1567. since we'll be doing so at regular intervals. The other is just to cache the
  1568. signal name so we don't need to create a new StringName every time.
  1569. In the source ``gdexample.c`` file we can change the constructor and destructor
  1570. to deal with the new fields:
  1571. .. code-block:: c
  1572. void gdexample_class_constructor(GDExample *self)
  1573. {
  1574. ...
  1575. self->time_emit = 0.0;
  1576. // Construct the StringName for the signal.
  1577. constructors.string_name_new_with_latin1_chars(&self->position_changed, "position_changed", false);
  1578. }
  1579. void gdexample_class_destructor(GDExample *self)
  1580. {
  1581. // Destruct the StringName for the signal.
  1582. destructors.string_name_destructor(&self->position_changed);
  1583. }
  1584. It is important to destruct the StringName to avoid memory leaks.
  1585. Now we can add to the ``gdexample_class_process()`` function to actually emit the
  1586. signal:
  1587. .. code-block:: c
  1588. void gdexample_class_process(GDExample *self, double delta)
  1589. {
  1590. ...
  1591. self->time_emit += delta;
  1592. if (self->time_emit >= 1.0)
  1593. {
  1594. // Call the emit_signal method.
  1595. call_2_args_stringname_vector2_no_ret_variant(methods.object_emit_signal, self->object, &self->position_changed, &new_position);
  1596. self->time_emit = 0.0;
  1597. }
  1598. }
  1599. This updates the time passed for the signal emission and, if it is over one
  1600. second it calls the ``emit_signal()`` function on the current instance, passing
  1601. the name of the signal and the new position as arguments.
  1602. Now we're done with our C GDExtension. Build it once more and reopen the demo
  1603. project in the editor.
  1604. In the documentation page for ``GDExample`` you can see the new signal we bound:
  1605. .. image:: img/gdextension_c_signal_doc.webp
  1606. To check it's working, let's add a small script to the root node, parent of our
  1607. custom one, that prints the position to the output every time it receives the
  1608. signal:
  1609. .. code-block:: gdscript
  1610. extends Node2D
  1611. func _ready():
  1612. $GDExample.position_changed.connect(on_position_changed)
  1613. func on_position_changed(new_position):
  1614. prints("New position:", new_position)
  1615. Run the project and you can observe the values being printed in the Output dock
  1616. in the editor:
  1617. .. image:: img/gdextension_c_signal_print.webp
  1618. Conclusion
  1619. ----------
  1620. This tutorial shows a basic extension with custom methods, properties, and
  1621. signals. While it does require a good amount of boilerplate, it can scale well
  1622. by creating helper functions to handle the tedious tasks.
  1623. This should serve as a good basis to understand the GDExtension API and as a
  1624. starting point to create custom binding generators. In fact, it would be
  1625. possible to create bindings for C using such type of generator, making the
  1626. actual coding look more like the ``gdexample.c`` file in this example, which is
  1627. quite straightforward and not very verbose.
  1628. If you want to create actual extensions, it is preferred to use the C++ bindings
  1629. instead, as it takes away all of the boilerplate from your code. Check the
  1630. :ref:`GDExtension C++ example <doc_gdextension_cpp_example>` to see how you can
  1631. do this.