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
Si necesitas una interacción personalizada de bajo nivel con software o hardware externo donde Lua no sea suficiente, el SDK de Defold te permite escribir extensiones para el motor en C, C++, Objective C, Java o JavaScript, según la plataforma objetivo. Los casos de uso típicos para las extensiones nativas son:
Defold proporciona un punto de entrada sin configuración para extensiones nativas con una solución de build basada en la nube. Cualquier extensión nativa que se desarrolle y se agregue a un proyecto de juego, ya sea directamente o mediante un proyecto de biblioteca, pasa a formar parte del contenido ordinario del proyecto. No hay necesidad de crear versiones especiales del motor y distribuirlas a los miembros del equipo; eso se gestiona automáticamente: cualquier miembro del equipo que cree y ejecute el proyecto obtendrá un ejecutable del motor específico del proyecto con todas las extensiones nativas incluidas.

Defold proporciona el servidor de build en la nube de forma gratuita, sin restricciones de uso. El servidor está alojado en Europa, y la URL a la que se envía el código nativo se configura en la ventana Editor Preferences o mediante la opción de línea de comando --build-server de bob. Si quieres configurar tu propio servidor, sigue estas instrucciones.
Para crear una extensión nueva, crea una carpeta en la raíz del proyecto. Esta carpeta contendrá toda la configuración, el código fuente, las librerías y los recursos asociados con la extensión. El builder de extensiones reconoce la estructura de carpetas y recopila cualquier archivo fuente y librería.
myextension/
│
├── ext.manifest
│
├── src/
│
├── include/
│
├── lib/
│ └──[platforms]
│
├── manifests/
│ └──[platforms]
│
└── res/
└──[platforms]
platform o architecture-platform, según las arquitecturas que soporten tus librerías.
Las plataformas compatibles son ios, android, osx, win32, linux, web.
Los pares arc-platform compatibles son arm64-ios, x86_64-ios, armv7-android, arm64-android, arm64-osx, x86_64-osx, x86-win32, x86_64-win32, arm64-linux, x86_64-linux, wasm-web y wasm_pthread-web.
platform o architecture-platform, igual que las subcarpetas de “lib”. También se permite una subcarpeta common, que contiene archivos de recursos comunes para todas las plataformas.La carpeta opcional manifests de una extensión contiene archivos adicionales usados en el proceso de build y bundling. Los archivos deben colocarse en subcarpetas nombradas por platform:
android - Esta carpeta acepta un archivo stub de manifest para fusionarlo con la aplicación principal (como se describe aquí).
build.gradle con dependencias para ser resueltas por Gradle.ios - Esta carpeta acepta un archivo stub de manifest para fusionarlo con la aplicación principal (como se describe aquí).
Podfile con dependencias para ser resueltas por Cocoapods.osx - Esta carpeta acepta un archivo stub de manifest para fusionarlo con la aplicación principal (como se describe aquí).web - Esta carpeta acepta un archivo stub de manifest para fusionarlo con la aplicación principal (como se describe aquí).Las extensiones se tratan igual que cualquier otro asset en tu proyecto y se pueden compartir de la misma manera. Si una carpeta de extensión nativa se agrega como carpeta de Library, puede compartirse y otros pueden usarla como dependencia del proyecto. Consulta el manual de proyectos de biblioteca para obtener más información.
Vamos a crear una extensión muy sencilla. Primero, creamos una nueva carpeta raíz myextension y agregamos un archivo ext.manifest que contiene el nombre de la extensión “MyExtension”. Ten en cuenta que el nombre es un símbolo C++ y debe coincidir con el primer argumento de DM_DECLARE_EXTENSION (ver más abajo).

# Símbolo C++ en tu extensión
name: "MyExtension"
La extensión consta de un único archivo C++, myextension.cpp, que se crea en la carpeta “src”.

El archivo fuente de la extensión contiene el siguiente código:
// myextension.cpp
// Defines de la librería de la extensión
#define LIB_NAME "MyExtension"
#define MODULE_NAME "myextension"
// Incluye el SDK de Defold
#include <dmsdk/sdk.h>
static int Reverse(lua_State* L)
{
// El número de elementos esperados en la pila de Lua
// una vez que este struct salga del scope
DM_LUA_STACK_CHECK(L, 1);
// Comprueba y obtiene el parámetro string desde la pila
char* str = (char*)luaL_checkstring(L, 1);
// Invierte el 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 el string invertido en la pila
lua_pushstring(L, str);
// Devuelve 1 elemento
return 1;
}
// Funciones expuestas a Lua
static const luaL_reg Module_methods[] =
{
{"reverse", Reverse},
{0, 0}
};
static void LuaInit(lua_State* L)
{
int top = lua_gettop(L);
// Registra nombres 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;
}
// El SDK de Defold usa una macro para configurar los puntos de entrada de la extensión:
//
// DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
// MyExtension es el símbolo C++ que contiene todos los datos relevantes de la extensión.
// Debe coincidir con el campo name en `ext.manifest`
DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, 0, 0, FinalizeMyExtension)
Observa la macro DM_DECLARE_EXTENSION, que se usa para declarar los distintos puntos de entrada al código de la extensión. El primer argumento, symbol, debe coincidir con el nombre especificado en ext.manifest. Para este ejemplo sencillo, no hay necesidad de puntos de entrada “update” ni “on_event”, por lo que se proporciona 0 en esas posiciones de la macro.
Ahora solo queda crear la build del proyecto (Project ▸ Build). Esto subirá la extensión al builder de extensiones, que producirá un motor personalizado con la nueva extensión incluida. Si el builder encuentra errores, se mostrará un diálogo con los errores de build.
Para probar la extensión, crea un objeto de juego y agrega un componente script con algo de código de prueba:
local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
local reverse_s = myextension.reverse(s)
print(reverse_s) --> ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba
Eso es todo. Hemos creado una extensión nativa completamente funcional.
Como vimos más arriba, la macro DM_DECLARE_EXTENSION se usa para declarar los distintos puntos de entrada al código de la extensión:
DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
Los puntos de entrada te permiten ejecutar código en distintos momentos del ciclo de vida de una extensión:
app_init de la extensióninit de la extensión - Se han inicializado todas las API de Defold. Este es el punto recomendado del ciclo de vida de la extensión para crear bindings Lua al código de la extensión.init() de los archivos script.update de la extensiónupdate() de los archivos script.on_event de la extensiónfinal() de los archivos script.final de la extensiónapp_final de la extensiónEl builder define los siguientes identificadores en cada plataforma respectiva:
DM_PLATFORM_WINDOWSDM_PLATFORM_OSXDM_PLATFORM_IOSDM_PLATFORM_ANDROIDDM_PLATFORM_LINUXDM_PLATFORM_HTML5Los logs del servidor de build están disponibles cuando el proyecto usa extensiones nativas. El log del servidor de build (log.txt) se descarga junto con el motor personalizado cuando se crea la build del proyecto, se almacena dentro del archivo .internal/%platform%/build.zip y también se descomprime en la carpeta de build de tu proyecto.
El Asset Portal de Defold también contiene varias extensiones nativas.