Reverse engeneering

Dunque: abbiamo fatto tutto meccanicamente e senza capirci un’emerita mazza, ma sarebbe strano il contrario, sinceramente. Adesso cerchiamo di entrare nel vivo, per capire come orientarci nel mondo di GDExtension. Scoprirete che di comodo non c’è un granché, ma il titolo di tutto il tutorial è eloquente abbastanza (credo) e quindi evitate di lamentarvi e seguitemi…


SConstruct

VSC1 è una specie di coltellino svizzero, fin troppo, se si vuole… Apre qualsiasi roba, anche ciò che non capisce. Questa cosa ci torna utile…

Guardate la Fig.6: con una freccia verde ho indicato il file SConstruct che ci interessa, lo stesso che abbiamo incollato dal file .zip che vi ho fatto scaricare. Questo file è fornito direttamente dalla guida di Godot relativa a GDExtension e non è dato sapere molto altro. C’è una postilla in merito al fatto che, in futuro, avrebbero scritto due righe sul come si fa, ma non si è visto ancora nulla (aprile 2025).

Proviamo a capirci qualcosa da soli. Se date un’occhiata alle righe puntate dalle frecce blu, è abbastanza chiaro che siano tutte riferite ad una specie di pattern che serve per dare un nome ad un file. Confrontate quelle righe con il file indicato dalla freccia rossa e… Ci siete arrivati, vero? Questo codice assegna nomi chilometrici, ma molto esplicativi, alle DLL create in base alla loro destinazione d’uso finale, intesa per sistemi operativi. Nell’immagine, è tagliata fuori la riga che interessa sia Windows che Linux. A parte il fatto che potete guardarvela sul vostro VSC, non è molto diversa dalle altre. Metti, quindi, che volessimo dare un nome più regale alla nostra libreria, ci basterà intervenire qui dentro per raggiungere il nostro obiettivo.

SConstruct è un file standard usato da SCons, sostanzialmente uno script Python che fa robe nel mentre della compilazione. Ovviamente, bisogna sapere cosa SCons si aspetta di ricevere, per poter procedere, e per quello vi arrangiate con la sua guida ufficiale2. Dal canto nostro, rimanendo sul semplice, sappiamo dove mettere le mani per cambiare nome alla libreria e adeguare il path al nostro progetto in Godot.

Visto che ci siamo, l’immagine ha catturato la finestra in basso a destra che chiede se siamo interessati ad installare l’interprete di Python. A noi non serve, ma se voleste… Intanto è chiaro che VSC ha capito che SConstruct è un file Python in ogni caso e si è adeguato.


gdexample.gdextension

Andiamo a dare un’occhiata, ora, ad un altro file che abbiamo incollato impunemente. Come mostra l’immagine dell Fig.7, si trova sotto la cartella demo/bin il che, se vi ricordate, lo pone proprio all’interno del nostro progetto Godot. Dico una cosa non ovvia, ma sperimentata personalmente: il nome del file non è importante. Conta solo la sua estensione, .gdextension. E’ chiaro che Godot controlla tutti questi files alla ricerca di qualcosa. Diamo un’occhiata alla sua organizzazione interna.

Sembra strutturato proprio come un file .ini di Windows. Ci sono diverse sezioni indicate da nomi tra parentesi quadre. Nella sezione libraries c’è un elenco che associa, chiaramente, ad ogni versione di sistema operativo, la sua libreria. La voce dependencies prevede file del tipo xcframework ma solo per iOS. Più interessante di tutte la sezione configuration dove sono presenti un parametro configuration_minimum che si riferisce, chiaramente, alla versione di Godot minima richiesta per caricare una di queste librerie. Poi c’è questa voce relodable impostata a true che permette il caricamento della libreria, in Godot, subito dopo la compilazione.

Ho lasciato per ultimo il parametro più interessante: entry_symbol. Qui apriamo una piccola parentesi. All’inizio di tutto il tutorial, ho accennato ad un vecchio trucco utilizzato per estendere i programmi: quello delle DLL. Pare che le DLL ci siano, ma a cosa serve un punto di accesso? Per dirla in soldoni, le DLL possono essere usate in due modi diversi: come parti di un programma più grande di cui si carica solo ciò che serve quando serve, per non intasare la memoria, oppure come espansioni delle capacità dell’applicativo.

Nel primo caso, si sa già cosa c’è all’interno delle librerie ed esse esistono solo per sgravare il carico di lavoro dalla RAM. Per fare un esempio: immaginate di avere un grosso CAD. Inutile caricare tutto il programma in un blocco solo. Se caricate la sezione del disegno, quindi, viene contestualmente caricata la DLL o le DLL che servono per farla funzionare. Poi la chiudete ed aprite un’altra funzione del programma. Contestualmente, vengono scaricate le DLL precedenti e ne vengono caricate altre. Ovviamente, si sa perfettamente quali sono le funzioni, classi o risorse all’interno delle varie DLL.

Nel secondo caso, invece, le DLL si usano per espandere le capacità di un programma che, in altre parole, acquisisce nuove funzionalità. Piccolo problema: come fa il programmatore a sapere quali sono le DLL che verranno sviluppate in futuro? Entra in gioco un entry point, ovvero un punto d’accesso, qualcosa di standardizzato che permetta di capire come caricare la libreria, anche se mai vista prima. Il vecchio trucco… Ricordatevi di quell’entry_symbol: vedremo presto come viene usato.

Nota a margine: abbiamo già accennato alla possibilità di compilare in modi diversi, portando l’esempio delle librerie a 64bit. Pare ovvio che, nel caso in cui si compili con l’opzione precision=double, i nomi delle DLL rifletteranno questo tipo di compilazione e che, quindi, dovranno essere modificati i nomi dei files nella sezione libraries .


register_types.h e register_types.cpp

Siccome voi conoscete il C++ come le vostre tasche (vero?), non c’è bisogno che vi spieghi come mai ci sono questi due files con stesso nome ma estensioni diverse. Diamo un’occhiata, piuttosto, al loro contenuto in Fig.8.

La prima cosa che scopriremo è che, in realtà, sono scritti in linguaggio C: sorprende poco, visto che C++ è un superset di C…

Cosa ancora di poca sorpresa è il fatto che nel file header sono riportati solo i prototipi delle funzioni il cui contenuto è nel file .cpp.

Diamo un’occhiata alla sezione contrassegnata da extern “C”: c’è una sola funzione chiamata… come l’entry_symbol all’interno del file .gdextension! Vuoi vedere che…

Notate, in fine, la macro GDREGISTER_RUNTIME_CLASS interna alla funzione initialize_example_module. Ve lo anticipo perché sono magnanimo: è proprio la classe contenuta nei file gdexample.h e gdexample.cpp che andremo a modificare più avanti. Sembra che abbiamo trovato il bandolo della matassa dopo tutto, no? Riepilogozzo:

  • Il file SConstruct è usato da SCons per generare le librerie DLL a partire dal nostro codice, quello che non abbiamo ancora visto. Possiamo modificare il nome delle librerie che verranno create, una per ogni configurazione target di Godot.
  • Il file .gdextension è utilizzato dall’editor di Godot, ma anche in runtime, per fornire le informazioni necessarie a caricare le DLL aggiuntive compilate con GDExtension in C++, dove ci metteremo dentro le nostre classi customizzate.
  • Una funzione con un prototipo ben preciso, ma che ha lo stesso nome dell’entry_symbol contenuto nel file .gdextension è il punto di accesso alla DLL per collegarla al resto del programma scritto con Godot, magari in GDScript.

gdexample.h e gdexample.cpp

Rimane solo da illustrare i due files contenenti i sorgenti della classe vera e propria, quella che darebbe un senso a tutto il codice GDExtension che abbiamo copiato fino a qui.

L’unica cosa che mi preme di far notare è che la classe GDExample è proprio la stessa che è stata registrata, in precedenza, nel codice in register_types.cpp attraverso la macro GDREGISTER_RUNTIME_CLASS. Per il resto, dimenticatevela pure che, tanto, ne facciamo una tutta nostra a partire dal prossimo articolo.


Sappiamo, quindi, dove mettere le mani per personalizzare il nostro codice, adesso. L’idea di base è che conviene impostare il lavoro partendo da questi files, che faranno un po’ da guida a tutto il processo di creazione. Dopo li andrete a modificare di conseguenza e cum grano salis, in modo che rispecchino i vostri desideri. Ora, capito il tutto, proviamo ad inventarci un progetto per mettere alla prova GDExtension. Diciamo che l’MMO strafigo ve lo fate da soli… Io, invece vorrei creare qualcosa di molto meno complesso, ma forse più utile: una specie di benchmark per mettere a confronto il codice scritto in C++ con quello scritto in GDScript valutandone la differenza in termini di prestazioni.


  1. Abbreviazione standard per Visual Studio Code… ↩︎
  2. Link al Wiki di SCons ↩︎

Reverse engeneering

Dunque: abbiamo fatto tutto meccanicamente e senza capirci un’emerita mazza, ma sarebbe strano il contrario, sinceramente. Adesso cerchiamo di entrare nel vivo, per capire come orientarci nel mondo di GDExtension. Scoprirete che di comodo non c’è un granché, ma il titolo di tutto il tutorial è eloquente abbastanza (credo) e quindi evitate di lamentarvi e seguitemi…


SConstruct

VSC1 è una specie di coltellino svizzero, fin troppo, se si vuole… Apre qualsiasi roba, anche ciò che non capisce. Questa cosa ci torna utile…

Guardate la Fig.6: con una freccia verde ho indicato il file SConstruct che ci interessa, lo stesso che abbiamo incollato dal file .zip che vi ho fatto scaricare. Questo file è fornito direttamente dalla guida di Godot relativa a GDExtension e non è dato sapere molto altro. C’è una postilla in merito al fatto che, in futuro, avrebbero scritto due righe sul come si fa, ma non si è visto ancora nulla (aprile 2025).

Proviamo a capirci qualcosa da soli. Se date un’occhiata alle righe puntate dalle frecce blu, è abbastanza chiaro che siano tutte riferite ad una specie di pattern che serve per dare un nome ad un file. Confrontate quelle righe con il file indicato dalla freccia rossa e… Ci siete arrivati, vero? Questo codice assegna nomi chilometrici, ma molto esplicativi, alle DLL create in base alla loro destinazione d’uso finale, intesa per sistemi operativi. Nell’immagine, è tagliata fuori la riga che interessa sia Windows che Linux. A parte il fatto che potete guardarvela sul vostro VSC, non è molto diversa dalle altre. Metti, quindi, che volessimo dare un nome più regale alla nostra libreria, ci basterà intervenire qui dentro per raggiungere il nostro obiettivo.

SConstruct è un file standard usato da SCons, sostanzialmente uno script Python che fa robe nel mentre della compilazione. Ovviamente, bisogna sapere cosa SCons si aspetta di ricevere, per poter procedere, e per quello vi arrangiate con la sua guida ufficiale2. Dal canto nostro, rimanendo sul semplice, sappiamo dove mettere le mani per cambiare nome alla libreria e adeguare il path al nostro progetto in Godot.

Visto che ci siamo, l’immagine ha catturato la finestra in basso a destra che chiede se siamo interessati ad installare l’interprete di Python. A noi non serve, ma se voleste… Intanto è chiaro che VSC ha capito che SConstruct è un file Python in ogni caso e si è adeguato.


gdexample.gdextension

Andiamo a dare un’occhiata, ora, ad un altro file che abbiamo incollato impunemente. Come mostra l’immagine dell Fig.7, si trova sotto la cartella demo/bin il che, se vi ricordate, lo pone proprio all’interno del nostro progetto Godot. Dico una cosa non ovvia, ma sperimentata personalmente: il nome del file non è importante. Conta solo la sua estensione, .gdextension. E’ chiaro che Godot controlla tutti questi files alla ricerca di qualcosa. Diamo un’occhiata alla sua organizzazione interna.

Sembra strutturato proprio come un file .ini di Windows. Ci sono diverse sezioni indicate da nomi tra parentesi quadre. Nella sezione libraries c’è un elenco che associa, chiaramente, ad ogni versione di sistema operativo, la sua libreria. La voce dependencies prevede file del tipo xcframework ma solo per iOS. Più interessante di tutte la sezione configuration dove sono presenti un parametro configuration_minimum che si riferisce, chiaramente, alla versione di Godot minima richiesta per caricare una di queste librerie. Poi c’è questa voce relodable impostata a true che permette il caricamento della libreria, in Godot, subito dopo la compilazione.

Ho lasciato per ultimo il parametro più interessante: entry_symbol. Qui apriamo una piccola parentesi. All’inizio di tutto il tutorial, ho accennato ad un vecchio trucco utilizzato per estendere i programmi: quello delle DLL. Pare che le DLL ci siano, ma a cosa serve un punto di accesso? Per dirla in soldoni, le DLL possono essere usate in due modi diversi: come parti di un programma più grande di cui si carica solo ciò che serve quando serve, per non intasare la memoria, oppure come espansioni delle capacità dell’applicativo.

Nel primo caso, si sa già cosa c’è all’interno delle librerie ed esse esistono solo per sgravare il carico di lavoro dalla RAM. Per fare un esempio: immaginate di avere un grosso CAD. Inutile caricare tutto il programma in un blocco solo. Se caricate la sezione del disegno, quindi, viene contestualmente caricata la DLL o le DLL che servono per farla funzionare. Poi la chiudete ed aprite un’altra funzione del programma. Contestualmente, vengono scaricate le DLL precedenti e ne vengono caricate altre. Ovviamente, si sa perfettamente quali sono le funzioni, classi o risorse all’interno delle varie DLL.

Nel secondo caso, invece, le DLL si usano per espandere le capacità di un programma che, in altre parole, acquisisce nuove funzionalità. Piccolo problema: come fa il programmatore a sapere quali sono le DLL che verranno sviluppate in futuro? Entra in gioco un entry point, ovvero un punto d’accesso, qualcosa di standardizzato che permetta di capire come caricare la libreria, anche se mai vista prima. Il vecchio trucco… Ricordatevi di quell’entry_symbol: vedremo presto come viene usato.

Nota a margine: abbiamo già accennato alla possibilità di compilare in modi diversi, portando l’esempio delle librerie a 64bit. Pare ovvio che, nel caso in cui si compili con l’opzione precision=double, i nomi delle DLL rifletteranno questo tipo di compilazione e che, quindi, dovranno essere modificati i nomi dei files nella sezione libraries .


register_types.h e register_types.cpp

Siccome voi conoscete il C++ come le vostre tasche (vero?), non c’è bisogno che vi spieghi come mai ci sono questi due files con stesso nome ma estensioni diverse. Diamo un’occhiata, piuttosto, al loro contenuto in Fig.8.

La prima cosa che scopriremo è che, in realtà, sono scritti in linguaggio C: sorprende poco, visto che C++ è un superset di C…

Cosa ancora di poca sorpresa è il fatto che nel file header sono riportati solo i prototipi delle funzioni il cui contenuto è nel file .cpp.

Diamo un’occhiata alla sezione contrassegnata da extern “C”: c’è una sola funzione chiamata… come l’entry_symbol all’interno del file .gdextension! Vuoi vedere che…

Notate, in fine, la macro GDREGISTER_RUNTIME_CLASS interna alla funzione initialize_example_module. Ve lo anticipo perché sono magnanimo: è proprio la classe contenuta nei file gdexample.h e gdexample.cpp che andremo a modificare più avanti. Sembra che abbiamo trovato il bandolo della matassa dopo tutto, no? Riepilogozzo:

  • Il file SConstruct è usato da SCons per generare le librerie DLL a partire dal nostro codice, quello che non abbiamo ancora visto. Possiamo modificare il nome delle librerie che verranno create, una per ogni configurazione target di Godot.
  • Il file .gdextension è utilizzato dall’editor di Godot, ma anche in runtime, per fornire le informazioni necessarie a caricare le DLL aggiuntive compilate con GDExtension in C++, dove ci metteremo dentro le nostre classi customizzate.
  • Una funzione con un prototipo ben preciso, ma che ha lo stesso nome dell’entry_symbol contenuto nel file .gdextension è il punto di accesso alla DLL per collegarla al resto del programma scritto con Godot, magari in GDScript.

gdexample.h e gdexample.cpp

Rimane solo da illustrare i due files contenenti i sorgenti della classe vera e propria, quella che darebbe un senso a tutto il codice GDExtension che abbiamo copiato fino a qui.

L’unica cosa che mi preme di far notare è che la classe GDExample è proprio la stessa che è stata registrata, in precedenza, nel codice in register_types.cpp attraverso la macro GDREGISTER_RUNTIME_CLASS. Per il resto, dimenticatevela pure che, tanto, ne facciamo una tutta nostra a partire dal prossimo articolo.


Sappiamo, quindi, dove mettere le mani per personalizzare il nostro codice, adesso. L’idea di base è che conviene impostare il lavoro partendo da questi files, che faranno un po’ da guida a tutto il processo di creazione. Dopo li andrete a modificare di conseguenza e cum grano salis, in modo che rispecchino i vostri desideri. Ora, capito il tutto, proviamo ad inventarci un progetto per mettere alla prova GDExtension. Diciamo che l’MMO strafigo ve lo fate da soli… Io, invece vorrei creare qualcosa di molto meno complesso, ma forse più utile: una specie di benchmark per mettere a confronto il codice scritto in C++ con quello scritto in GDScript valutandone la differenza in termini di prestazioni.


  1. Abbreviazione standard per Visual Studio Code… ↩︎
  2. Link al Wiki di SCons ↩︎

Ultima modifica: