Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Vinculación a bibliotecas externas

Módulos

The Summator example in Módulos personalizados en C++ is great for small, custom modules, but what if you want to use a larger, external library? Let's look at an example using Festival, a speech synthesis (text-to-speech) library written in C++.

Para vincular una biblioteca externa, configura un directorio de módulos similar al ejemplo del Summator:

godot/modules/tts/

Next, you will create a header file with a TTS class:

/* tts.h */

#ifndef GODOT_TTS_H
#define GODOT_TTS_H

#include "core/object/ref_counted.h"

class TTS : public RefCounted {
    GDCLASS(TTS, RefCounted);

protected:
    static void _bind_methods();

public:
    bool say_text(String p_txt);

    TTS();
};

#endif // GODOT_TTS_H

Y luego agregarás el archivo cpp.

/* tts.cpp */

#include "tts.h"

#include <festival.h>

bool TTS::say_text(String p_txt) {

    //convert Godot String to Godot CharString to C string
    return festival_say_text(p_txt.ascii().get_data());
}

void TTS::_bind_methods() {

    ClassDB::bind_method(D_METHOD("say_text", "txt"), &TTS::say_text);
}

TTS::TTS() {
    festival_initialize(true, 210000); //not the best way to do it as this should only ever be called once.
}

Al igual que antes, la nueva clase necesita ser registrada de alguna manera, por lo que se deben crear dos archivos más:

register_types.h
register_types.cpp

Importante

Los archivos anteriores deben estar en la carpeta de nivel superior de tu módulo (junto a tus archivos SCsub y config.py) para que el módulo se registre correctamente.

Estos archivos deberán contener lo siguiente:

/* register_types.h */

void initialize_tts_module(ModuleInitializationLevel p_level);
void uninitialize_tts_module(ModuleInitializationLevel p_level);
/* yes, the word in the middle must be the same as the module folder name */
/* register_types.cpp */

#include "register_types.h"

#include "core/object/class_db.h"
#include "tts.h"

void initialize_tts_module(ModuleInitializationLevel p_level) {
    if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
        return;
    }
    ClassDB::register_class<TTS>();
}

void uninitialize_tts_module(ModuleInitializationLevel p_level) {
    // Nothing to do here in this example.
}

A continuación, debes crear un archivo SCsub para que el sistema de compilación compile este módulo:

# SCsub

Import('env')

env_tts = env.Clone()
env_tts.add_source_files(env.modules_sources, "*.cpp") # Add all cpp files to the build

Necesitarás instalar la biblioteca externa en tu máquina para obtener los archivos de biblioteca .a. Consulta la documentación oficial de la biblioteca para obtener instrucciones específicas sobre cómo hacerlo para tu sistema operativo. Hemos incluido los comandos de instalación para Linux a continuación, como referencia.

sudo apt-get install festival festival-dev <-- Installs festival and speech_tools libraries
apt-cache search festvox-* <-- Displays list of voice packages
sudo apt-get install festvox-don festvox-rablpc16k festvox-kallpc16k festvox-kdlpc16k <-- Installs voices

Importante

Las voces que utiliza Festival (y cualquier otro recurso externo o de terceros potencial) tienen diferentes licencias y términos de uso; algunos (si no la mayoría) de ellos pueden ser problemáticos con Godot, incluso si la propia biblioteca de Festival es compatible con la Licencia MIT. Asegúrate de verificar las licencias y los términos de uso.

La biblioteca externa también deberá ser instalada dentro de tu módulo para que los archivos fuente sean accesibles al compilador, al mismo tiempo que mantienes el código del módulo autocontenido. Las bibliotecas festival y speech_tools se pueden instalar desde el directorio modules/tts/ a través de git utilizando los siguientes comandos:

git clone https://github.com/festvox/festival
git clone https://github.com/festvox/speech_tools

Si no deseas que los archivos fuente del repositorio externo se incluyan en tu propio repositorio, puedes enlazarlos agregándolos como submódulos (desde el directorio modules/tts/), como se muestra a continuación:

git submodule add https://github.com/festvox/festival
git submodule add https://github.com/festvox/speech_tools

Importante

Please note that Git submodules are not used in the Godot repository. If you are developing a module to be merged into the main Godot repository, you should not use submodules. If your module doesn't get merged in, you can always try to implement the external library as a GDExtension.

Puedes agregar directorios de inclusión a las rutas de entorno para que sean vistos por el compilador:

# These paths are relative to /modules/tts/
env_tts.Append(CPPPATH=["speech_tools/include", "festival/src/include"])

# LIBPATH and LIBS need to be set on the real "env" (not the clone)
# to link the specified libraries to the Godot executable.

# This is a path relative to /modules/tts/ where your .a libraries reside.
# If you are compiling the module externally (not in the godot source tree),
# these will need to be full paths.
env.Append(LIBPATH=['libpath'])

# Check with the documentation of the external library to see which library
# files should be included/linked.
env.Append(LIBS=['Festival', 'estools', 'estbase', 'eststring'])

Si deseas agregar banderas personalizadas del compilador al construir tu módulo, primero debes clonar env, para evitar que agregue esas banderas a toda la compilación de Godot (lo que puede causar errores). A continuación, te muestro un ejemplo de SCsub con banderas personalizadas:

# SCsub

Import('env')

env_tts = env.Clone()
env_tts.add_source_files(env.modules_sources, "*.cpp")
    # Append CCFLAGS flags for both C and C++ code.
env_tts.Append(CCFLAGS=['-O2'])
# If you need to, you can:
# - Append CFLAGS for C code only.
# - Append CXXFLAGS for C++ code only.

El módulo debería verse así:

godot/modules/tts/festival/
godot/modules/tts/libpath/libestbase.a
godot/modules/tts/libpath/libestools.a
godot/modules/tts/libpath/libeststring.a
godot/modules/tts/libpath/libFestival.a
godot/modules/tts/speech_tools/
godot/modules/tts/config.py
godot/modules/tts/tts.h
godot/modules/tts/tts.cpp
godot/modules/tts/register_types.h
godot/modules/tts/register_types.cpp
godot/modules/tts/SCsub

Usar el módulo

Ahora puede usar su módulo recién creado desde cualquier script:

var t = TTS.new()
var script = "Hello world. This is a test!"
var is_spoken = t.say_text(script)
print('is_spoken: ', is_spoken)

Y la salida será is_spoken: True si el texto es hablado.