This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Se você precisa de interação personalizada com software ou hardware externo em baixo nível, onde Lua não é suficiente, o SDK do Defold permite escrever extensões para a engine em C, C++, Objective C, Java ou Javascript, dependendo da plataforma-alvo. Casos de uso típicos para extensões nativas são:
O Defold oferece um ponto de entrada sem configuração para extensões nativas com uma solução de build baseada em nuvem. Qualquer extensão nativa desenvolvida e adicionada a um projeto de jogo, diretamente ou por meio de um projeto de biblioteca, passa a fazer parte do conteúdo comum do projeto. Não é necessário compilar versões especiais da engine e distribuí-las aos membros da equipe; isso é feito automaticamente: qualquer membro da equipe que compilar e executar o projeto receberá um executável da engine específico do projeto, com todas as extensões nativas incorporadas.

O Defold fornece o servidor de build em nuvem gratuitamente, sem restrições de uso. O servidor é hospedado na Europa, e a URL para a qual o código nativo é enviado é configurada na janela de Preferências do Editor ou pela opção de linha de comando --build-server do bob. Se quiser configurar seu próprio servidor, siga estas instruções.
Para criar uma nova extensão, crie uma pasta na raiz do projeto. Essa pasta conterá todas as configurações, código-fonte, bibliotecas e recursos associados à extensão. O builder de extensão reconhece a estrutura de pastas e coleta todos os arquivos-fonte e bibliotecas.
myextension/
│
├── ext.manifest
│
├── src/
│
├── include/
│
├── lib/
│ └──[platforms]
│
├── manifests/
│ └──[platforms]
│
└── res/
└──[platforms]
platform, ou architecture-platform, dependendo de quais arquiteturas suas bibliotecas aceitam.
As plataformas suportadas são ios, android, osx, win32, linux, web.
Os pares arc-platform suportados são arm64-ios, x86_64-ios, armv7-android, arm64-android, arm64-osx, x86_64-osx, x86-win32, x86_64-win32, arm64-linux, x86_64-linux, js-web, wasm-web e wasm_pthread-web.
platform, ou architecture-platform, assim como as subpastas de “lib”. Uma subpasta common também é permitida, contendo arquivos de recurso comuns a todas as plataformas.A pasta opcional manifests de uma extensão contém arquivos adicionais usados no processo de build e empacotamento. Os arquivos devem ser colocados em subpastas nomeadas por platform:
android - Esta pasta aceita um arquivo stub de manifesto a ser mesclado na aplicação principal (conforme descrito aqui).
build.gradle com dependências a serem resolvidas pelo Gradle.ios - Esta pasta aceita um arquivo stub de manifesto a ser mesclado na aplicação principal (conforme descrito aqui).
Podfile com dependências a serem resolvidas pelo Cocoapods.osx - Esta pasta aceita um arquivo stub de manifesto a ser mesclado na aplicação principal (conforme descrito aqui).web - Esta pasta aceita um arquivo stub de manifesto a ser mesclado na aplicação principal (conforme descrito aqui).Extensões são tratadas como qualquer outro asset no seu projeto e podem ser compartilhadas da mesma forma. Se uma pasta de extensão nativa for adicionada como pasta de biblioteca, ela poderá ser compartilhada e usada por outras pessoas como uma dependência de projeto. Consulte o manual de projeto de biblioteca para mais informações.
Vamos criar uma extensão bem simples. Primeiro, criamos uma nova pasta raiz myextension e adicionamos um arquivo ext.manifest contendo o nome da extensão “MyExtension”. Observe que o nome é um símbolo C++ e deve corresponder ao primeiro argumento de DM_DECLARE_EXTENSION (veja abaixo).

# Símbolo C++ na sua extensão
name: "MyExtension"
A extensão consiste em um único arquivo C++, myextension.cpp, criado na pasta “src”.

O arquivo-fonte da extensão contém o seguinte código:
// myextension.cpp
// Definições da lib da extensão
#define LIB_NAME "MyExtension"
#define MODULE_NAME "myextension"
// Inclui o SDK do Defold
#include <dmsdk/sdk.h>
static int Reverse(lua_State* L)
{
// O número de itens esperados na pilha Lua
// quando esta struct sair de escopo
DM_LUA_STACK_CHECK(L, 1);
// Verifica e obtém a string de parâmetro da pilha
char* str = (char*)luaL_checkstring(L, 1);
// Inverte a string
int len = strlen(str);
for(int i = 0; i < len / 2; i++) {
const char a = str[i];
const char b = str[len - i - 1];
str[i] = b;
str[len - i - 1] = a;
}
// Coloca a string invertida na pilha
lua_pushstring(L, str);
// Retorna 1 item
return 1;
}
// Funções expostas para Lua
static const luaL_reg Module_methods[] =
{
{"reverse", Reverse},
{0, 0}
};
static void LuaInit(lua_State* L)
{
int top = lua_gettop(L);
// Registra nomes Lua
luaL_register(L, MODULE_NAME, Module_methods);
lua_pop(L, 1);
assert(top == lua_gettop(L));
}
dmExtension::Result AppInitializeMyExtension(dmExtension::AppParams* params)
{
return dmExtension::RESULT_OK;
}
dmExtension::Result InitializeMyExtension(dmExtension::Params* params)
{
// Inicializa Lua
LuaInit(params->m_L);
printf("Registered %s Extension\n", MODULE_NAME);
return dmExtension::RESULT_OK;
}
dmExtension::Result AppFinalizeMyExtension(dmExtension::AppParams* params)
{
return dmExtension::RESULT_OK;
}
dmExtension::Result FinalizeMyExtension(dmExtension::Params* params)
{
return dmExtension::RESULT_OK;
}
// O SDK do Defold usa uma macro para configurar pontos de entrada da extensão:
//
// DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
// MyExtension é o símbolo C++ que contém todos os dados relevantes da extensão.
// Ele deve corresponder ao campo name em `ext.manifest`
DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, 0, 0, FinalizeMyExtension)
Observe a macro DM_DECLARE_EXTENSION, usada para declarar os vários pontos de entrada no código da extensão. O primeiro argumento symbol deve corresponder ao nome especificado em ext.manifest. Para este exemplo simples, não há necessidade de pontos de entrada “update” ou “on_event”, então 0 é fornecido nessas posições da macro.
Agora basta compilar o projeto (Projeto ▸ Compilar). Isso enviará a extensão ao builder de extensões, que produzirá uma engine personalizada com a nova extensão incluída. Se o builder encontrar algum erro, uma caixa de diálogo com os erros de build será exibida.
Para testar a extensão, crie um objeto de jogo e adicione um componente de script com algum código de teste:
local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
local reverse_s = myextension.reverse(s)
print(reverse_s) --> ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba
E pronto! Criamos uma extensão nativa totalmente funcional.
Como vimos acima, a macro DM_DECLARE_EXTENSION é usada para declarar os vários pontos de entrada no código da extensão:
DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
Os pontos de entrada permitem executar código em vários momentos do ciclo de vida de uma extensão:
app_init da extensãoinit da extensão - Todas as APIs do Defold foram inicializadas. Este é o ponto recomendado no ciclo de vida da extensão em que os bindings Lua para o código da extensão são criados.init() dos arquivos de script é chamada.update da extensãoupdate() dos arquivos de script é chamada.on_event da extensãofinal() dos arquivos de script é chamada.final da extensãoapp_final da extensãoOs seguintes identificadores são definidos pelo builder em cada plataforma respectiva:
DM_PLATFORM_WINDOWSDM_PLATFORM_OSXDM_PLATFORM_IOSDM_PLATFORM_ANDROIDDM_PLATFORM_LINUXDM_PLATFORM_HTML5Os logs do servidor de build ficam disponíveis quando o projeto usa extensões nativas. O log do servidor de build (log.txt) é baixado junto com a engine personalizada quando o projeto é compilado e armazenado dentro do arquivo .internal/%platform%/build.zip, além de ser descompactado na pasta de build do seu projeto.
O portal de assets do Defold também contém várias extensões nativas.