Определение функций C
Чтобы зарегистрировать функцию C в Lua, имеется следующая макрокоманда:
#define lua_register(L, n, f) (lua_pushcfunction(L,f),lua_setglobal(L,n)) /* const char *n; */ /* lua_CFunction f; */
Которая получает имя, которое функция будет иметь в Lua, и указатель на функцию. Этот указатель должен иметь тип lua_CFunction, который определен так; typedef int (*lua_CFunction) (lua_State *L);
То есть, это указатель на функцию с целочисленным результатом и одиночным параметром, Lua-средой.
Чтобы связываться правильно с Lua, функция C должна следовать следующему протоколу, который определяет путь, которым параметры и результаты переданы: функция C получает параметры от Lua в стеке, в прямом порядке (первый параметр помещен первым). Чтобы возвращать значения Lua, функция C только помещает их в стек в прямом порядке и возвращает число результатов. Подобно функции Lua, функция C, вызванная Lua, может возвращать много результатов.
Как пример, следующая функция получает переменное число числовых параметров, а возвращает их среднее и сумму: static int foo (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ double sum = 0; int i;
for (i = 1; i <= n; i++) { if (!lua_isnumber(L, i)) lua_error(L, "incorrect argument to function `average'"); sum += lua_tonumber(L, i); } lua_pushnumber(L, sum/n); /* первый результат */ lua_pushnumber(L, sum); /* второй результат */ return 2; /* сколько всего результатов */ }
Эта функция может быть зарегистрирована в Lua как average таким вызовом: lua_register(L, "average", foo);
Когда функция C создана, возможно сопоставить с ней некоторые upvalues, таким образом создавая замкнутое выражение C; эти значения будут переданы функции всякий раз, когда она вызвана, как обычные параметры. Чтобы сопоставить upvalues с функцией C, сначала эти значения должны быть помещены в стек. Затем функция void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
используется, чтобы поместить функцию C в стек с параметром n означающим, сколько upvalues должно быть связан с функцией (эти upvalues берутся из стека). Фактически, макрокоманда lua_pushcfunction определена как lua_pushcclosure с n установленным в 0. Затем, всякий раз, когда функция C вызвана, эти upvalues вставлены как последние параметры функции, после фактических параметров, переданных в обращении. Это избавляет от необходимости выяснять, сколько параметров было передано фактически. Так i-th upvalue находится в стеке в индексе i-(n+1), где n задает номер upvalues.
Для большего количества примеров функций C и замкнутых выражений изучите файлы lbaselib.c, liolib.c, lmathlib.c и lstrlib.c в дистрибутиве Lua.