Связывание внешних библиотек

Модули

The Summator example in Собственные модули на 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++.

Для связки внешней библиотеки, установить директорию модуля подобно примеру с Summator :

godot/modules/tts/

Далее, вы должны создать заголовочный файл с простым классом TTS:

/* tts.h */

#ifndef GODOT_TTS_H
#define GODOT_TTS_H

#include "core/reference.h"

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

protected:
    static void _bind_methods();

public:
    bool say_text(String p_txt);

    TTS();
};

#endif // GODOT_TTS_H

И затем вы добавляете файл 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.
}

Также как и ранее, новый класс нуждается в регистрации, так что нужно добавить ещё два файла:

register_types.h
register_types.cpp

Важно

These files must be in the top-level folder of your module (next to your SCsub and config.py files) for the module to be registered properly.

These files should contain the following:

/* register_types.h */

void register_tts_types();
void unregister_tts_types();
/* yes, the word in the middle must be the same as the module folder name */
/* register_types.cpp */

#include "register_types.h"

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

void register_tts_types() {
    ClassDB::register_class<TTS>();
}

void unregister_tts_types() {
    // Nothing to do here in this example.
}

Далее, вы должны создать файл SCsub чтобы система сборки скомпилировала модуль:

# SCsub

Import('env')

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

Вам нужно установить внешнюю библиотеку на ваш компьютер чтобы получить библиотечные файлы .a. Посмотрите в официальную документацию библиотеки для инструкций о том как получить их для вашей операционной системы. Мы включили команды установки для Linux ниже, для справки.

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

Важно

The voices that Festival uses (and any other potential external/3rd-party resource) all have varying licenses and terms of use; some (if not most) of them may be be problematic with Godot, even if the Festival Library itself is MIT License compatible. Please be sure to check the licenses and terms of use.

Внешнюю библиотеке нужно также установить внутри вашего модуля чтобы сделать файлы исходного кода доступными для компилятора, а также сохраняя код модуля самодостаточным. Библиотеки festival и speech_tools могут быть установлены из папки modules/tts/ через git используя следующие команды:

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

Если вы не хотите чтобы внешние кодовые файлы репозитория соединились с вашим репозиторием, вы может связаться с ними вместо добавления их как под-модулей (внутри папки modules/tts/), как показано ниже:

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

Важно

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 GDNative C++ plugin.

Чтобы добавить директории включения(include) для компилятора, вы может добавить их в пути переменных сред:

# 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'])

Если вы желаете добавить собственные флаги компиляции когда строите модуль, вы должны сначала клонировать env, чтобы он не добавлял флаги целиком в Godot (что вызовет ошибки). К примеру SCsub с собственными флагами:

# SCsub

Import('env')

env_tts = env.Clone()
env_tts.add_source_files(env.modules_sources, "*.cpp")
env_tts.Append(CCFLAGS=['-O2']) # Flags for C and C++ code
env_tts.Append(CXXFLAGS=['-std=c++11']) # Flags for C++ code only

В итоге скрипт должен выглядеть так:

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

Использование модуля

Теперь вы можете использовать ваш новый модуль из любого скрипта:

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

А вывод будет is_spoken: True если текст будет произнесён.