外部ライブラリへのバインド

モジュール

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.
}

前と同じように、新しいクラスを何らかの方法で登録する必要があるため、さらに2つのファイルを作成する必要があります:

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ライブラリは、次のコマンドを使用して、gitを介してmodules/ tts/ディレクトリからインストールできます:

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.

コンパイラが見るインクルードディレクトリを追加するには、環境のパスに追加します:

# 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 になります。