Topik ini menjelaskan model skrip pada aplikasi host, yaitu pola ketika aplikasi utama membawa penerjemah Lua dan membuka sebagian API-nya kepada skrip. Bahasan mencakup dua arah integrasi antara host dan skrip, alasan Lua sering dipilih sebagai bahasa tersemat, peran nyata yang sudah dijalankan oleh Lua pada perangkat lunak yang ada, serta batas lingkup jalur ini pada model dan konsep API C. Setelah topik ini dibaca, peran penerjemah, skrip, dan kode host pada aplikasi yang menyematkan Lua sudah tergambar dengan jelas.
Aplikasi host dan lapisan skrip#
Aplikasi host adalah aplikasi utama yang memuat penerjemah Lua ke dalam prosesnya. Aplikasi semacam ini dapat ditulis dalam C, C++, atau bahasa lain yang mampu memanggil pustaka C, sedangkan Lua berperan sebagai lapisan skrip di atasnya. Host mendefinisikan API domain, yaitu kumpulan fungsi yang menyingkap kemampuan aplikasi kepada skrip, misalnya membaca berkas konfigurasi, menggambar objek, atau menyimpan catatan ke basis data. Skrip tidak pernah berdiri sendiri karena seluruh kemampuannya berasal dari fungsi yang dibuka host.
Integrasi berjalan dua arah. Pada arah pertama, host memuat berkas skrip dan mengeksekusinya pada titik tertentu, misalnya saat aplikasi dimulai, saat pengguna menekan tombol, atau saat peristiwa tertentu terjadi. Pada arah kedua, skrip memanggil fungsi yang disediakan host untuk memengaruhi perilaku aplikasi, misalnya menyimpan pengaturan atau mencatat kejadian. Kedua arah itu dipertemukan oleh satu saluran yang sama, yaitu stack, tumpukan nilai pada API C milik penerjemah.
Pola ini menjelaskan mengapa dua aplikasi yang sama-sama menyematkan Lua dapat menawarkan fungsi yang sama sekali berbeda. Penerjemahnya sama, sedangkan API domain milik masing-masing host. Pengetahuan tentang bahasa Lua tetap berlaku di mana pun hostnya berada, tetapi daftar fungsi yang dapat dipanggil skrip selalu merujuk pada dokumentasi host yang bersangkutan.
Alasan Lua dipilih sebagai bahasa tersemat#
Menyematkan bahasa lain menuntut biaya yang kecil pada sisi aplikasi host. Lua ditulis dalam C yang mengikuti standar ISO, sehingga penerjemahnya dapat dikompilasi di hampir semua platform dan berukuran jauh lebih kecil daripada penerjemah bahasa pada umumnya. Antarmukanya berupa pustaka C yang bersih, yaitu sekumpulan fungsi dengan peran yang jelas, sehingga penyematan tidak menuntut alat tambahan di luar compiler C.
Di sisi skrip, pengetikan dinamis membuat berkas konfigurasi mudah dibaca dan disunting tanpa deklarasi tipe. Table menjadi satu-satunya struktur data sekaligus format data yang ekspresif, karena struktur bersarang ditulis langsung sebagai nilai. Blok berikut menunjukkan sebuah berkas skrip bergaya konfigurasi yang dimuat host. Nilai batas_arsip dan table arsip di dalamnya dapat disunting tanpa kompilasi ulang aplikasi, dan logika skrip yang membaca keduanya ikut berubah perilaku.
-- berkas skrip yang dimuat aplikasi host
-- nilai berikut dapat disunting tanpa kompilasi ulang aplikasi
batas_arsip = 2
arsip = {
"log-suhu-2024.csv",
"log-suhu-2023.csv",
"log-suhu-2022.csv",
}
for i = 1, #arsip do
if i <= batas_arsip then
print("diarsipkan", arsip[i])
end
enddiarsipkan log-suhu-2024.csv
diarsipkan log-suhu-2023.csvKeluaran memperlihatkan dua berkas arsip yang lolos batas. Apabila nilai batas_arsip diubah menjadi 3, baris ketiga ikut tercetak dan aplikasi host tidak perlu dikompilasi ulang. Perubahan kecil semacam ini merupakan alasan utama pemindahan perilaku ke lapisan skrip, karena bagian yang sering berubah berhenti berada di dalam kode yang dikompilasi.
Alasan terakhir adalah kemudahan membuat sandbox, yaitu lingkungan eksekusi yang kemampuannya dibatasi secara sengaja. Host menentukan pustaka apa saja yang dibuka dan fungsi apa saja yang tersedia bagi skrip, sehingga skrip yang tidak sepenuhnya dipercaya dapat dijalankan tanpa akses penuh ke sistem. Bagian ini tidak membahas pembangunannya, tetapi kemudahan pembatasan inilah yang menjadikan Lua layak dipercaya pada lingkungan semacam skrip server.
Peran nyata Lua yang tersemat#
Model tersebut sudah berjalan pada banyak perangkat lunak yang digunakan sehari-hari. Addon antarmuka gim World of Warcraft, misalnya, ditulis dalam Lua di atas API domain milik mesin gimnya, sehingga pengaya yang disunting pemain berjalan di atas penerjemah yang disematkan klien gim. Neovim menyematkan Lua untuk konfigurasi dan plugin, sedangkan server Redis mengeksekusi skrip atomik yang dikirim klien melalui perintah EVAL. Contoh-contoh ini disebut sebagai fakta teknis tentang penyebaran Lua, bukan sebagai rekomendasi produk.
Peran Lua pada ketiga contoh itu berbeda. Pada addon gim, Lua menjadi pelapis antarmuka yang berinteraksi dengan API gim. Pada penyunting teks, Lua menjadi bahasa konfigurasi yang mengendalikan perilaku aplikasi. Pada server, Lua menjadi sarana menjalankan logika kecil di dekat data dengan jaminan atomisitas. Ketiganya berbagi satu pola yang sama dengan model di atas, yaitu host yang membuka API domain dan skrip yang memanggilnya.
Batas lingkup dan host C pertama#
Seri ini membahas model dan konsep API C, bukan panduan langkah demi langkah membangun aplikasi host lengkap. Tujuannya adalah memahami apa yang terjadi ketika host memuat skrip, sehingga contoh C berikutnya berbentuk potongan yang fokus pada mekanismenya. Kompilasi potongan tersebut memerlukan kepala pustaka Lua dan pustaka Lua dari distribusi resminya, misalnya dengan perintah gcc host.c -llua -o host pada lingkungan yang memasang Lua beserta pustaka pengembangannya. Nama pustakanya dapat berbeda menurut distribusi, misalnya -llua5.4 pada beberapa sistem.
Potongan berikut memperlihatkan bentuk host C yang paling sederhana. Fungsi luaL_newstate membuat penerjemah baru, luaL_openlibs membuka pustaka bawaan, dan luaL_dofile memuat serta mengeksekusi berkas skrip. Apabila host.c dan atur.lua diletakkan pada direktori yang sama lalu program dikompilasi dan dijalankan, host mencetak dua baris arsip yang sama dengan keluaran di atas, kemudian berakhir dengan sukses.
// tidak-dijalankan
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
int main(void) {
/* 1. buat penerjemah Lua baru */
lua_State *L = luaL_newstate();
if (L == NULL) {
fprintf(stderr, "penerjemah tidak dapat dibuat\n");
return 1;
}
/* 2. buka pustaka bawaan Lua */
luaL_openlibs(L);
/* 3. muat dan jalankan berkas skrip */
if (luaL_dofile(L, "atur.lua") != LUA_OK) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_close(L);
return 1;
}
/* 4. lepaskan penerjemah sebelum program berakhir */
lua_close(L);
return 0;
}Setiap langkah pada potongan itu menjadi fondasi bagi contoh C selanjutnya pada jalur ini. Penerjemah diwakili oleh objek lua_State, pesan error pemuatan dibaca dari stack, dan pustaka yang dibuka menentukan batas kemampuan skrip. Pemetaan tersebut membuat contoh yang lebih panjang tetap mudah diikuti karena bentuknya tidak berubah.
Ringkasan#
- Aplikasi host memuat penerjemah Lua ke dalam prosesnya dan membuka API domain kepada skrip, sedangkan skrip memanggil fungsi host untuk memengaruhi perilaku aplikasi.
- Integrasi berjalan dua arah dan dipertemukan oleh stack pada API C milik penerjemah.
- Lua dipilih karena penerjemahnya kecil dan cepat, pustaka C-nya bersih, pengetikannya dinamis, table-nya berlaku sebagai format data, dan sandbox-nya mudah dibatasi.
- Host C minimal terdiri atas
luaL_newstate,luaL_openlibs, danluaL_dofile, lalu dikompilasi bersama pustaka Lua dari distribusi resminya.
Referensi#
- Manual Referensi Lua 5.4 — Lua.org — Bagian Introduction dan The Application Program Interface menjelaskan konsep aplikasi host serta API C.
- Programming in Lua, edisi pertama — Lua.org — Bab-bab C API memperagakan model host yang memuat dan mengeksekusi skrip.