binding_to_external_libraries.rst 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. .. _doc_binding_to_external_libraries:
  2. Binding to external libraries
  3. =============================
  4. Modules
  5. -------
  6. The Summator example in :ref:`_doc_custom_modules_in_c++` is great for small, custom modules, but
  7. what if you want to use a larger, external library? Let's look at an example
  8. using Festival, a speech synthesis (text-to-speech) library written in C++.
  9. To bind to an external library, set up a module directory similar to the Summator example:
  10. ::
  11. godot/modules/tts/
  12. Next, you will create a header file with a simple TTS class:
  13. .. code:: cpp
  14. /* tts.h */
  15. #ifndef GODOT_TTS_H
  16. #define GODOT_TTS_H
  17. #include <reference.h>
  18. class TTS : public Reference {
  19. GDCLASS(TTS, Reference);
  20. protected:
  21. static void _bind_methods();
  22. public:
  23. bool say_text(String txt);
  24. TTS();
  25. };
  26. #endif // GODOT_TTS_H
  27. And then you'll add the cpp file.
  28. .. code:: cpp
  29. /* tts.cpp */
  30. #include "tts.h"
  31. #include "festival/src/include/festival.h"
  32. bool TTS::say_text(String txt) {
  33. //convert Godot String to Godot CharString to C string
  34. return festival_say_text(txt.ascii().get_data());
  35. }
  36. void TTS::_bind_methods() {
  37. ClassDB::bind_method(D_METHOD("say_text", "txt"), &TTS::say_text);
  38. }
  39. TTS::TTS() {
  40. festival_initialize(true, 210000); //not the best way to do it as this should only ever be called once.
  41. }
  42. Just as before, the new class needs to be registered somehow, so two more files
  43. need to be created:
  44. ::
  45. register_types.h
  46. register_types.cpp
  47. With the following contents:
  48. .. code:: cpp
  49. /* register_types.h */
  50. void register_tts_types();
  51. void unregister_tts_types();
  52. /* yes, the word in the middle must be the same as the module folder name */
  53. .. code:: cpp
  54. /* register_types.cpp */
  55. #include "register_types.h"
  56. #include "class_db.h"
  57. #include "tts.h"
  58. void register_tts_types() {
  59. ClassDB::register_class<TTS>();
  60. }
  61. void unregister_tts_types() {
  62. //nothing to do here
  63. }
  64. Next, you need to create a ``SCsub`` file so the build system compiles
  65. this module:
  66. .. code:: python
  67. # SCsub
  68. Import('env')
  69. env_tts = env
  70. env_tts.add_source_files(env.modules_sources,"*.cpp") # Add all cpp files to the build
  71. You'll need to install the external library on your machine to get the .a library files. See the library's official
  72. documentation for specific instructions on how to do this for your operation system. We've included the
  73. installation commands for Linux below, for reference.
  74. ::
  75. sudo apt-get install festival festival-dev <-- Installs festival and speech_tools libraries
  76. apt-cache search festvox-* <-- Displays list of voice packages
  77. sudo apt-get install festvox-don festvox-rablpc16k festvox-kallpc16k festvox-kdlpc16k <-- Installs voices
  78. .. note::
  79. **Important** The voices that Festival uses (and any other potential external/3rd-party
  80. resource) all have varying licenses and terms of use; some (if not most) of them may be
  81. be problematic with Godot, even if the Festival Library itself is MIT License compatible.
  82. Please be sure to check the licenses and terms of use.
  83. The external library will also need to be installed inside your module to make the source
  84. files accessible to the compiler, while also keeping the module code self-contained. The
  85. festival and speech_tools libraries can be installed from the modules/tts/ directory via
  86. git using the following commands:
  87. ::
  88. git clone https://github.com/festvox/festival
  89. git clone https://github.com/festvox/speech_tools
  90. If you don't want the external repository source files committed to your repository, you
  91. can link to them instead by adding them as submodules (from within the modules/tts/ directory), as seen below:
  92. ::
  93. git submodule add https://github.com/festvox/festival
  94. git submodule add https://github.com/festvox/speech_tools
  95. .. note::
  96. **Important** Please note that Git submodules are not used in the Godot repository. If
  97. you are developing a module to be merged into the main Godot repository, you should not
  98. use submodules. If your module doesn't get merged in, you can always try to implement
  99. the external library as a GDNative C++ plugin.
  100. To add include directories for the compiler to look at you can append it to the
  101. environment's paths:
  102. .. code:: python
  103. env_tts.Append(CPPPATH="speech_tools/include", "festival/src/include") # this is a path relative to /modules/tts/
  104. # http://www.cstr.ed.ac.uk/projects/festival/manual/festival_28.html#SEC132 <-- Festival library documentation
  105. env_tts.Append(LIBPATH=['libpath']) # this is a path relative to /modules/tts/ where your .a library files reside
  106. # You should check with the documentation of the external library to see which library files should be included/linked
  107. env_tts.Append(LIBS=['Festival', 'estools', 'estbase', 'eststring'])
  108. If you want to add custom compiler flags when building your module, you need to clone
  109. `env` first, so it won't add those flags to whole Godot build (which can cause errors).
  110. Example `SCsub` with custom flags:
  111. .. code:: python
  112. # SCsub
  113. Import('env')
  114. env_tts = env
  115. env_tts.add_source_files(env.modules_sources,"*.cpp")
  116. env_tts.Append(CXXFLAGS=['-O2', '-std=c++11'])
  117. The final module should look like this:
  118. ::
  119. godot/modules/tts/festival/
  120. godot/modules/tts/libpath/libestbase.a
  121. godot/modules/tts/libpath/libestools.a
  122. godot/modules/tts/libpath/libeststring.a
  123. godot/modules/tts/libpath/libFestival.a
  124. godot/modules/tts/speech_tools/
  125. godot/modules/tts/config.py
  126. godot/modules/tts/tts.h
  127. godot/modules/tts/tts.cpp
  128. godot/modules/tts/register_types.h
  129. godot/modules/tts/register_types.cpp
  130. godot/modules/tts/SCsub
  131. Using the module
  132. ----------------
  133. You can now use your newly created module from any script:
  134. ::
  135. var t = TTS.new()
  136. var script = "Hello world. This is a test!"
  137. var is_spoken = t.say_text(script)
  138. print('is_spoken: ', is_spoken)
  139. And the output will be ``is_spoken: True`` if the text is spoken.