Native extensions - kuimoani/defold GitHub Wiki
Native extensions
λ§μ½ Luaλ‘λ μΆ©λΆνμ§ λͺ»ν μΈλΆ μννΈμ¨μ΄λ νλμ¨μ΄μ λ‘μ° λ λ²¨λ‘ μ»€μ€ν μνΈμμ©μ΄ νμν κ²½μ°μλ, Defold SDKλ C++λ‘ μ΅μ€ν μ μ λ§λ€ μ μμ΅λλ€. λ€μ΄ν°λΈ μ΅μ€ν μ μ μΌλ°μ μΈ μ¬μ© μ¬λ‘λ‘λ λ€μκ³Ό κ°μ΅λλ€.
- μλ₯Ό λ€λ©΄ λͺ¨λ°μΌ μΉ΄λ©λΌ κ°μ νΉμ νλμ¨μ΄μ μνΈμμ© νκΈ°
- κ΄κ³ λ€νΈμν¬ APIλ Luasocketμ μ¬μ©ν μ μλ λ€νΈμν¬ API κ°μ μΈλΆ λ‘μ° λ 벨 APIμ μνΈμμ© νκΈ°
- κ³ μ±λ₯ κ³μ°
The build platform
Defoldλ ν΄λΌμ°λ κΈ°λ° λΉλ μ루μ μ μ¬μ©νμ¬ λ€μ΄ν°λΈ μ΅μ€ν μ μ λν 무μ€μ μ§μ μ§μ (zero setup entry point)μ μ 곡ν©λλ€. κ²μ νλ‘μ νΈμ μΆκ°λ λ€μ΄ν°λΈ μ΅μ€ν μ μ μΌλ°μ μΈ νλ‘μ νΈ μ»¨ν μΈ μ μΌλΆκ° λ©λλ€. μμ§μ νΉμ λ²μ μΌλ‘ λΉλνκ±°λ νμμκ² λ°°ν¬ν νμλ μμΌλ©° μ΄ μμ λ€μ μλμΌλ‘ μ΄λ£¨μ΄μ§λλ€. νλ‘μ νΈλ₯Ό λΉλνκ±°λ μ€ννλ €λ λͺ¨λ νμλ€μ λͺ¨λ λ€μ΄ν°λΈ μ΅μ€ν μ κ³Ό ν¨κ» νΉμ νλ‘μ νΈ μμ§ μ€ννμΌμ λ°μ μ μμ΅λλ€.

Project layout
μ μ΅μ€ν μ μ λ§λ€κΈ° μν΄μλ νλ‘μ νΈ λ£¨νΈμ ν΄λλ₯Ό νλ λ§λ€μ΄μΌ ν©λλ€. μ΄ ν΄λμλ μ΅μ€ν μ κ³Ό κ΄κ³λ λͺ¨λ μ ν , μμ€μ½λ, λΌμ΄λΈλ¬λ¦¬, 리μμ€λ€μ ν¬ν¨μμΌμΌ ν©λλ€. μ΄ μ΅μ€ν μ λΉλλ ν΄λ ꡬ쑰λ₯Ό μΈμνκ³ λͺ¨λ μμ€νμΌκ³Ό λΌμ΄λΈλ¬λ¦¬λ₯Ό μμ§ν©λλ€.

"ext.manifest"
μ΅μ€ν μ ν΄λμλ "ext.manifest" νμΌμ΄ μμ΄μΌ ν©λλ€. μ΄ νμΌμ μ΅μ€ν μ λΉλμ μν΄ μ νλλ YAML νμμ νμΌμ λλ€. λ©λνμ€νΈ νμΌμλ μ΅μν μ΅μ€ν μ μ μ΄λ¦μ΄ ν¬ν¨λμ΄ μμ΄μΌ ν©λλ€.
src
μ΄ ν΄λμλ λͺ¨λ μμ€μ½λ νμΌλ€μ΄ μμ΄μΌ ν©λλ€.
include
μ΄ μ νμ (optional) ν΄λμλ λ€λ₯Έ ν¬ν¨ νμΌ(include files)λ€μ΄ μμ΄μΌ ν©λλ€.
lib
μ΄ μ νμ ν΄λμλ μ΅μ€ν μ μ΄ μμ‘΄νλ λͺ¨λ μ»΄νμΌλ λΌμ΄λΈλ¬λ¦¬λ€μ΄ μμ΄μΌ ν©λλ€. λΌμ΄λΈλ¬λ¦¬ νμΌλ€μ λΌμ΄λΈλ¬λ¦¬κ° μ§μνλ μν€ν μ³κ° 무μμΈμ§μ λ°λΌ νλ«νΌ λλ μν€ν μ³-νλ«νΌ μ΄λ¦μ νμ ν΄λμ μμ΄μΌ ν©λλ€. μ§μλλ νλ«νΌμ ios, android, osx μ΄λ©° μ§μλλ μν€ν μ³-νλ«νΌ μ(arc-platform pairs)μ armv7-ios, arm64-ios, armv7-android, x86_64-osx μ λλ€.
res
μ΄ μ νμ ν΄λμλ μ΅μ€ν μ μ΄ μμ‘΄νλ λͺ¨λ μΆκ° 리μμ€λ€μ΄ μμ΄μΌ ν©λλ€. 리μμ€ νμΌλ€μ "lib" νμ ν΄λμ²λΌ νλ«νΌ λλ μν€ν μ³-νλ«νΌ μ΄λ¦μ νμ ν΄λμ μμ΄μΌ ν©λλ€. common μ΄λ¦μ νμν΄λμλ λͺ¨λ νλ«νΌμ 곡ν΅μ μΈ λ¦¬μμ€ νμΌλ€μ ν¬ν¨μν¬ μ μμ΅λλ€.
A simple example extension
μμ£Ό κ°λ¨ν μ΅μ€ν μ μ κ°λ°ν΄ λ΄ μλ€. μ°μ , "myextension" μ΄λΌλ μ λ£¨νΈ ν΄λλ₯Ό λ§λ€κ³ μ΅μ€ν μ μ μ΄λ¦μ΄ μλ "ext.manifest" νμΌμ μΆκ°ν΄ λ΄ μλ€.

ext.manifest
name: "MyExtension"
μ΅μ€ν μ μ ꡬμ±νλ C++ νμΌ ν κ°λ₯Ό "myextension.cpp" λΌλ μ΄λ¦μΌλ‘ "src" ν΄λμ μμ±ν©λλ€.
Defold μλν°λ κΈ°λ³Έμ μΌλ‘ .cpp νμΌμ μ΄ μ μμΌλ―λ‘ νμΌμ λλΈ ν΄λ¦ν΄μ ν΄λΉ νμΌ νμ μ μ¬μ©λλ μμ€ν μλν°λ₯Ό μ¬μ©ν©λλ€. λ¬Όλ‘ ν΄λΉ νμΌμ λ§μ°μ€ μ€λ₯Έμͺ½ ν΄λ¦ν΄μ Open With βΈ Text Editor λ©λ΄λ₯Ό μ νν΄ λ΄μ₯λ ν μ€νΈ μλν°λ₯Ό μ¬μ©ν΄λ λμ§λ§, Defoldλ C++ νμΌμ μ§μνμ§ μμΌλ―λ‘ μ΅μνμ νΈμ§ κΈ°λ₯λ§ μ¬μ© κ°λ₯ν©λλ€.

μ΅μ€ν μ μμ€ νμΌμ μλ μ½λλ₯Ό ν¬ν¨ν©λλ€.
myextension.cpp
// Extension lib defines
#define LIB_NAME "MyExtension"
#define MODULE_NAME "myextension"
// include the Defold SDK
#include <dmsdk/sdk.h>
static int Rot13(lua_State* L)
{
int top = lua_gettop(L);
// μ€νμμ λ¬Έμμ΄ νλΌλ―Έν° 체ν¬νκ³ κ°μ Έμ€κΈ°
const char* str = luaL_checkstring(L, 1);
// μ λ¬Έμμ΄ ν λΉ
int len = strlen(str);
char *rot = (char *) malloc(len + 1);
// νλΌλ―Έν° λ¬Έμμ΄μ λ°λ³΅ν΄μ rot13 λ¬Έμμ΄ μμ±νκΈ°
for(int i = 0; i <= len; i++) {
const char c = str[i];
if((c >= 'A' && c <= 'M') || (c >= 'a' && c <= 'm')) {
// A~M μ¬μ΄μ charμ 13 λνκΈ°
rot[i] = c + 13;
} else if((c >= 'N' && c <= 'Z') || (c >= 'n' && c <= 'z')) {
// N~Z μ¬μ΄μ charμ 13μ λΉΌκΈ°
rot[i] = c - 13;
} else {
// λ¬Έμλ₯Ό κ·Έλλ‘ μ μ§ν¨
rot[i] = c;
}
}
// νμ λ λ¬Έμμ΄μ μ€νμ λ£μ
lua_pushstring(L, rot);
// λ¬Έμμ΄ λ©λͺ¨λ¦¬ ν΄μ . Luaλ μ§κΈ 볡μ λ³Έμ κ°μ§κ³ μμ
free(rot);
// μ€νμ νλμ μμ΄ν
μ΄ μμμ assert ν¨
assert(top + 1 == lua_gettop(L));
// 1 μμ΄ν
λ°ν
return 1;
}
// Luaμ λ
ΈμΆλ ν¨μ
static const luaL_reg Module_methods[] =
{
{"rot13", Rot13},
{0, 0}
};
static void LuaInit(lua_State* L)
{
int top = lua_gettop(L);
// 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)
{
// Init 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;
}
// Defold SDKλ μ΅μ€ν
μ
μ§μ
μ μ μ
ν
νκΈ° μν΄ λ§€ν¬λ‘λ₯Ό μ¬μ©ν¨
//
// DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, 0, 0, FinalizeMyExtension)
DM_DECLARE_EXTENSION λ§€ν¬λ‘λ μ΅μ€ν μ μ½λμ λ€μν μ§μ μ (entry points)μ μ μΈνλλ° μ¬μ©λ©λλ€. μ΄ κ°λ¨ν μμ μμλ, "update"λ "on_event" μ§μ μ μ΄ νμνμ§ μμΌλ―λ‘ λμ 0 κ°μ λ§€ν¬λ‘ μΈμκ°μΌλ‘ 보λ λλ€.
μ΄μ νλ‘μ νΈλ₯Ό λΉλ(Project βΈ Build and Launch)ν μ°¨λ‘μ λλ€. μ΄κ²μ μ΅μ€ν μ μ μ΅μ€ν μ λΉλμ μ λ‘λν΄μ μ μ΅μ€ν μ μ΄ ν¬ν¨λ 컀μ€ν μμ§μ μμ±ν©λλ€. λ§μ½ λΉλμ μλ¬κ° λ°μνλ©΄ λΉλ μλ¬κ° μλ λνμ°½μ νμν©λλ€.
μ΅μ€ν μ μ ν μ€νΈνλ €λ©΄, κ²μ μ€λΈμ νΈλ₯Ό μμ±ν΄μ μλμ κ°μ ν μ€νΈ μ½λκ° μλ μ€ν¬λ¦½νΈ μ»΄ν¬λνΈλ₯Ό μΆκ°ν΄μΌ ν©λλ€.
local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
local rot_s = myextension.rot13(s)
print(rot_s) --> nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM
μ΄μ λμ λλ€! μ°λ¦¬λ μμ ν μ λμνλ λ€μ΄ν°λΈ μ΅μ€ν μ μ λ§λ€μμ΅λλ€.
The ext.manifest file
λ©λνμ€νΈ νμΌμλ μ΅μ€ν μ μ μ΄λ¦ μΈμλ νΉμ νλ«νΌμ compile flags, link flags, libs, frameworks λ₯Ό μΆκ°ν μ μμ΅λλ€. μλμ μμ κ° μμ΅λλ€.
ext.manifest
name: "AdExtension"
platforms:
arm64-ios:
context:
frameworks: ["CoreGraphics", "CFNetwork", "GLKit", "CoreMotion", "MessageUI", "MediaPlayer", "StoreKit", "MobileCoreServices", "AdSupport", "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreTelephony", "CoreVideo", "Foundation", "GLKit", "JavaScriptCore", "MediaPlayer", "MessageUI", "MobileCoreServices", "OpenGLES", "SafariServices", "StoreKit", "SystemConfiguration", "UIKit", "WebKit"]
flags: ["-stdlib=libc++"]
linkFlags: ["-ObjC"]
libs: ["z", "c++", "sqlite3"]
armv7-ios:
context:
frameworks: ["CoreGraphics", "CFNetwork", "GLKit", "CoreMotion", "MessageUI", "MediaPlayer", "StoreKit", "MobileCoreServices", "AdSupport", "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreTelephony", "CoreVideo", "Foundation", "GLKit", "JavaScriptCore", "MediaPlayer", "MessageUI", "MobileCoreServices", "OpenGLES", "SafariServices", "StoreKit", "SystemConfiguration", "UIKit", "WebKit"]
flags: ["-stdlib=libc++"]
linkFlags: ["-ObjC"]
libs: ["z", "c++", "sqlite3"]
Known issues
λ€μ΄ν°λΈ μ΅μ€ν μ κΈ°λ₯μ μν(alpha) μνμ΄λ―λ‘, μμ§ λͺ¨λ κΈ°λ₯μ΄ μ€λΉλμ§λ μμμ΅λλ€.
- Platforms: νμ¬λ macOS, iOS, Android μ΅μ€ν μ λΉλλ§ μ§μν©λλ€.
- Android λ .java μ .jar archives μ λν μ§μμ΄ λΆμ‘±ν©λλ€.
- Editor: μλν° ν΅ν©(editor integration). λΉλ νλ‘μΈμ€κ° νμλμ§ μκ³ μλ¬ λ¦¬ν¬ν κΈ°λ₯λ μμ§ λͺλͺ κΈ°λ₯λ§ μ§μλ©λλ€.
- Debugging: νμ¬, iOSμμ λΉλνλ κ²½μ°, .dSYM νμΌμ΄ κ²°κ³Ό λΉλμ ν¬ν¨λκ³ μμ§ μμ΅λλ€.