|
@@ -0,0 +1,124 @@
|
|
|
+---
|
|
|
+title: Нативные расширения - Лучшие Практики
|
|
|
+brief: В этом руководстве описаны лучшие методы разработки нативных расширений.
|
|
|
+---
|
|
|
+
|
|
|
+# Лучшие Практики
|
|
|
+
|
|
|
+Написание кроссплатформенного кода может быть сложным, но есть некоторые способы облегчить его разработку и поддержку. В этом руководстве мы перечислим некоторые способы, с помощью которых мы в Defold работаем с кроссплатформенным нативным кодом и API.
|
|
|
+
|
|
|
+## Код Defold
|
|
|
+
|
|
|
+В движке Defold мы используем C++ очень мало. Фактически, большинство кода C-подобна. Мы избегаем шаблонов, за исключением нескольких контейнерных классов, из-за того, что шаблоны увеличивают как время компиляции, так и размер исполняемого файла.
|
|
|
+
|
|
|
+### C++ версия
|
|
|
+
|
|
|
+Исходный код Defold собирается с использованием версии C++ по умолчанию каждого компилятора (см. [Native Extensions - Best Practices](/manuals/extensions-best-practices/)).
|
|
|
+
|
|
|
+Мы избегаем использования последних возможностей или версий C++. В основном потому, что у нас уже есть все необходимое для создания игрового движка. Следить за последними возможностями C++ - трудоемкая задача, и чтобы действительно освоить эти возможности, потребуется много драгоценного времени.
|
|
|
+
|
|
|
+Для разработчиков расширений это также является дополнительным преимуществом, поскольку мы поддерживаем стабильный ABI. Также стоит отметить, что использование последних возможностей C++ может помешать компиляции кода на разных платформах из-за различной поддержки.
|
|
|
+
|
|
|
+### Стандартные Библиотеки Шаблонов - STL
|
|
|
+
|
|
|
+Поскольку движок Defold не использует никакого кода STL, за исключением некоторых алгоритмов и математики (std::sort, std::upper_bound и т.д.), но вы можете использовать STL в своем расширении.
|
|
|
+
|
|
|
+Опять же, имейте в виду, что несовместимость ABI может помешать вам при использовании вашего расширения в сочетании с другими расширениями или библиотеками сторонних производителей
|
|
|
+
|
|
|
+Избегая (сильно шаблонизированных) библиотек STL, мы также улучшаем время сборки и, что более важно, размер исполняемого файла.
|
|
|
+
|
|
|
+#### Строки
|
|
|
+
|
|
|
+В движке Defold мы используем `const char*` вместо `std::string`.
|
|
|
+
|
|
|
+`std::string` - распространенный подводный камень при смешивании различных версий C++ или версий компилятора: вы получите несоответствие ABI.
|
|
|
+Для нас лучше использовать `const char*` и несколько вспомогательных функций.
|
|
|
+
|
|
|
+### Создание скрытых функций
|
|
|
+
|
|
|
+По возможности используйте ключ `static` для функций, локальных для вашего блока компиляции. Это позволяет компилятору выполнять некоторые оптимизации, что может как улучшить производительность, так и уменьшить размер исполняемого файла.
|
|
|
+
|
|
|
+## Библиотеки сторонних производителей
|
|
|
+
|
|
|
+При выборе сторонней библиотеки для использования (независимо от языка) мы учитываем, по крайней мере, следующие моменты:
|
|
|
+
|
|
|
+* Функциональность - Решает ли он конкретную проблему, которая у вас есть?
|
|
|
+* Производительность - Влечет ли он за собой затраты на производительность во время выполнения?
|
|
|
+* Размер библиотеки - Насколько больше будет конечный исполняемый файл? Приемлемо ли это?
|
|
|
+* Зависимости - Требуются ли дополнительные библиотеки?
|
|
|
+* Поддержка - В каком состоянии находится библиотека? Много ли у нее открытых проблем? Поддерживается ли она до сих пор?
|
|
|
+* Лицензия - Можно ли ее использовать для этого проекта?
|
|
|
+
|
|
|
+
|
|
|
+## Зависимости с открытым исходным кодом
|
|
|
+
|
|
|
+Всегда убеждайтесь, что у вас есть доступ к зависимостям. Например, если вы зависите от чего-то на GitHub, ничто не помешает тому, что репозиторий будет удален, или внезапно изменит направление или владельца. Вы можете уменьшить этот риск, сделав форк репозитория и используя свой форк вместо проекта upstream.
|
|
|
+
|
|
|
+Код из этой библиотеки будет внедрен в вашу игру, поэтому убедитесь, что библиотека делает то, что должна делать, и ничего больше!
|
|
|
+
|
|
|
+
|
|
|
+## Структура проекта
|
|
|
+
|
|
|
+При создании расширения есть несколько вещей, которые помогают как в его разработке, так и в поддержании.
|
|
|
+
|
|
|
+### Lua API
|
|
|
+
|
|
|
+Должен быть только один Lua API и одна его реализация. Это значительно облегчает одинаковое поведение для всех платформ.
|
|
|
+
|
|
|
+Если рассматриваемая платформа не поддерживает расширение, мы рекомендуем просто не регистрировать модуль Lua вообще.
|
|
|
+Таким образом, вы можете обнаружить поддержку, проверив наличие nil:
|
|
|
+
|
|
|
+ if myextension ~= nil then
|
|
|
+ myextension.do_something()
|
|
|
+ end
|
|
|
+
|
|
|
+### Структура папки
|
|
|
+
|
|
|
+Вот структура папок, которую мы часто используем для наших расширений.
|
|
|
+
|
|
|
+ /root
|
|
|
+ /input
|
|
|
+ /main -- Все файлы для актуального примера проекта
|
|
|
+ /...
|
|
|
+ /myextension -- Фактическая корневая папка расширения
|
|
|
+ ext.manifest
|
|
|
+ /include -- Внешние включения, используемые другими расширениями
|
|
|
+ /libs
|
|
|
+ /<platform> -- Внешние библиотеки для всех поддерживаемых платформ
|
|
|
+ /src
|
|
|
+ myextension.cpp -- Lua API расширения и функции жизненного цикла расширения
|
|
|
+ Также содержимое общих реализаций ваших функций Lua API.
|
|
|
+ myextension_private.h -- Ваш внутренний API, который будет реализован на каждой платформе (например, `myextension_Init` и т.д.)
|
|
|
+ myextension.mm -- Если для iOS/macOS необходимы нативные вызовы. Реализует `myextension_Init` и т.д. для iOS/macOS
|
|
|
+ myextension_android.cpp -- Если для Android необходимы вызовы JNI. Реализуется `myextension_Init` и т.д. для Android
|
|
|
+ /java
|
|
|
+ /<platform> -- Любые java-файлы, необходимые для Android
|
|
|
+ /res -- Любые ресурсы, необходимые для платформы
|
|
|
+ /external
|
|
|
+ README.md -- Заметки/скрипты о том, как собрать или упаковать любые внешние библиотеки
|
|
|
+ /bundleres -- Ресурсы, для которых должны быть созданы связки (см. game.project и параметр [bundle_resources setting]([physics scale setting])(/manuals/project-settings/#project))
|
|
|
+ /<platform>
|
|
|
+ game.project
|
|
|
+ game.appmanifest -- Любая дополнительная информация о конфигурации приложения
|
|
|
+
|
|
|
+
|
|
|
+Обратите внимание, что `myextension.mm` и `myextension_android.cpp` нужны только в том случае, если вы делаете специфические нативные вызовы для данной платформы.
|
|
|
+
|
|
|
+#### Папки платформы
|
|
|
+
|
|
|
+В некоторых местах мы используем архитектуру платформы в качестве имени папки, чтобы знать, какие файлы использовать при компиляции/комплектации приложения.
|
|
|
+Они имеют такую форму:
|
|
|
+
|
|
|
+ <architecture>-<platform>
|
|
|
+
|
|
|
+Текущий список таков:
|
|
|
+
|
|
|
+ arm64-ios, armv7-ios, x86_64-ios, arm64-android, armv7-android, x86_64-linux, x86_64-osx, x86_64-win32, x86-win32
|
|
|
+
|
|
|
+Например, поместите библиотеки для конкретной платформы в раздел:
|
|
|
+
|
|
|
+ /libs
|
|
|
+ /arm64-ios
|
|
|
+ /libFoo.a
|
|
|
+ /arm64-android
|
|
|
+ /libFoo.a
|