eseguire istruzioni scritte in un linguaggio (es. Lua)
da un programma scritto in un altro (es. C o C++)
esempio: Edge, Firefox, Safari, etc.
all'interno della pagina:
<input type="button"
value="pulsante"
onClick="alert('ok');" />
sono programmi scritti in JavaScript,
eseguiti da Firefox, scritto in C
sono programmi scritti in GNU Guile e/o Python
eseguiti da gdb, scritto in C
user_pref("browser.download.panel.shown", true);
user_pref("browser.download.save_converter_index", 0);
user_pref("browser.tabs.closeWindowWithLastTab", false);
user_pref("browser.tabs.warnOnClose", true);
opzioni di Firefox
sempre in JavaScript
esempio: l'ultima linea dice di aprire una finestra di avvertimento quando si chiude il browser
char *strcpy(char *dest, const char *src)
{
int d0, d1, d2;
asm volatile("1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
: "0" (src), "1" (dest) : "memory");
return dest;
}
quasi tutto il kernel è scritto in C
esegue alcune istruzioni in linguaggio macchina
linux/arch/x86/lib/string_32.c
1: lodsb stosb testb %%al,%%al jne 1b
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
: "0" (src), "1" (dest) : "memory"
esempio: istruzioni lua eseguite un programma C
deve essere possibile:
ultima cosa: spiegata dopo
#include <stdlib.h>
…
int main() {
…
char *hello="print(\"hello, this is the lua snippet\")";
…
luaL_loadbuffer(ls, hello, strlen(hello), "name");
…
lua_pcall(ls, 0, 0, 0);
…
}
char *hello="print(\"hello, this is the lua snippet\")"; … luaL_loadbuffer(ls, hello, strlen(hello), "name");
lua_pcall(ls, 0, 0, 0);
avviene spesso attraverso una pila
struttura dati in cui è possibile inserire più dati
sono l'uno sopra l'altro
generalmente:
lua_pushnumber(ls, 2); lua_pushnumber(ls, -5); lua_pushnumber(ls, 23);
il programma C inserisce 2, -5 e 23 nella pila
il due è il primo
quindi va in fondo
i successivi sopra
| → |
| -5 |
+----+
| 2 |
+----+
|
→ |
| 23 | +----+ | -5 | +----+ | 2 | +----+ |
lua_remove(ls, -1); lua_remove(ls, -1); lua_pushnumber(ls, 9);
rimuove i due elementi in cima alla pila
ne aggiunge uno nuovo:
| 23 | +----+ | -5 | +----+ | 2 | +----+ |
→ |
| 2 |
+----+
|
→ |
| 9 |
+----+
| 2 |
+----+
|
val = lua_tonumber(ls, -1);
legge il dato in cima alla pila
allo stato attuale è il 9
| 9 |
+----+
| 2 |
+----+
lua_pushnumber(ls, 5); lua_setglobal(ls, "x");
lua_getglobal(ls, "x");
printf("z=%g\n", lua_tonumber(ls, -1));
char *function = " \ function xxx(x,y) \ print(x,y) \ return x+y+2 \ end \ "; … luaL_loadbuffer(ls, function, strlen(function), "function");
carica la stringa che contiene definizione della funzione
lua_pcall(ls, 0, 0, 0);
esegue la definizione della funzione
è lo stesso di function xxx(x,y) ... in lua
crea la funzione, ancora non la esegue
analogo a xxx = function(x,y) … end
crea la variabile xxx e ci mette la funzione
lua_getglobal(ls, "xxx");
carica la funzione sulla pila
in lua le funzioni sono valori
come i numeri, come le stringhe
in questo caso, è il valore memorizzato nella variabile xxx
si carica il valore della variabile xxx nella pila
| function(x,y) ... end |
+-----------------------+
lua_pushnumber(ls, 9); lua_pushnumber(ls, 4);
carica i dati nella pila
| 4 |
+-----------------------+
| 9 |
+-----------------------+
| function(x,y) ... end |
+-----------------------+
| 4 |
+-----------------------+
| 9 |
+-----------------------+
| function(x,y) ... end |
+-----------------------+
lua_pcall(ls, 2, 1, 0);
esegue la funzione sulla pila, con due argomenti
la pila ora contiene il risultato
| 15 |
+-----------------------+
| 15 |
+-----------------------+
val = lua_tonumber(ls, -1);
legge il valore in cima alla pila
solito sistema
esempio (JavaScript):
pagina web
visualizzata da Firefox, programma C
+---------------------+
| titolo |
| |
| pulsante testo |
+----|------------|---+
| |
| | script.js
| | programma JavaScript
+----|------------|------+
| V V |
| premuto() cambiato() |
| | |
+----|-------------------+
|
| pagina dei dati
V visualizzata da Firefox, programma c
+---------------------+
| dati |
| |
| a y r |
| 31.3 45.3 9.0 |
| 32.2 45.2 13.2 |
| -9.9 12.0 -4.1 |
+---------------------+
non sono dati di interesse all'interno del programma JavaScript
a JavaScript interessa solo che va eseguita una funzione C
non è nemmeno detto che i dati che siano di un tipo che lua riconosce
vengono passati C → lua → C
senza che lua li debba o voglia sapere di che tipo sono
sono come un pacco che un corriere consegna
non vede il contenuto
ma nemmeno gli interessa sapere cosa c'è dentro
pacco "opaco"
char *program = " \ print(\"start\") \ x,y = lua_aprifinestra(3,v) \ print(\"first return value: \",x) \ print(\"second return value: \",y) \ ";
chiama la funzione lua_aprifinesta()
verrè definita come una funzione C
int aprifinestra(lua_State *s) {
…
}
lua_register(ls, "lua_aprifinestra", aprifinestra);
dice che la funzione C aprifinestra si chiama lua_aprifinestra in lua
lua_pushlightuserdata(ls, &dato); lua_setglobal(ls, "v");
va nella variabile lua v
… x,y = lua_aprifinestra(3,v) …
chiama la funzione lua lua_aprifinestra
è associata alla funzione C aprifinestra
due argomenti
il primo è il numero 3
il secondo è il dato opaco proveniente dal C
int aprifinestra(lua_State *s) {
…
n = lua_gettop(s); // numero argomenti
x = lua_tonumber(s, 1); // dato lua, generato da lua
y = lua_touserdata(s, 2); // dato opaco, proveniente dal C
…
}
ogni linguaggio ha le sue specifiche funzioni
per interagire con istruzioni in altri linguaggi
es. lua, JavaScript, Python, Guile
ogni interprete JavaScript ha un suo meccanismo
diverso da quello degli altri
es. duktape, mujs, SpiderMonkey