Скомпилируйте скрипт Lua в буфер без знака - PullRequest
1 голос
/ 05 марта 2012

Я работаю на сервере в C, который динамически генерирует команды Lua на лету и отправляет их по сокетам клиентам. Сейчас сервер использует простой текст, но я бы хотел, чтобы сервер предварительно скомпилировал скрипт перед отправкой его клиентам.

Я проверяю luac.c, но не могу найти способ сделать что-то вроде этого:

char lua_commands[ 1024 ] = { "a = 123; b = 456; c = a + b;" };

int socket 
unsigned int send_buffer_size
unsigned char *send_buffer

/* Compile lua_commands and store the binary script into send_buffer without
having to write first the .out on disk then read it again in order store the content
into send_buffer */

send( socket, send_buffer, send_buffer_size, 0 );

Кто-нибудь может помочь мне достичь этого?

[Обновить]

Хорошо, думаю, я это выяснил:

#include "lua.h"
#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstring.h"
#include "lundump.h"


#define toproto(L,i) (clvalue(L->top+(i))->l.p)

static int writer( lua_State *L, const void *p, size_t size, void *u ){

    unsigned int i = 0;

    unsigned char *d = ( unsigned char * )p;

    // Print all the bytes on the console.
    while( i != size ) {
        printf("%d ", d[ i ] );
        ++i;
    }
    return 0;
}


void compile( lua_State *L, char *command ){

    const Proto* f;

    if (luaL_loadstring( L, command ) !=0 ) {
        printf( "%s\n", lua_tostring( L, -1 ) );
    }

    f = toproto( L,-1 );

    lua_lock( L );

    luaU_dump( L, f, writer, NULL, 1 );

    lua_unlock( L );    
}


int main (int argc, const char * argv[]) {

    lua_State *L = lua_open(); 

    compile( L, "a = 123; b = 456; c = a + b; print( c );" );

    lua_close( L );

    return 0;
}

Однако это подводит меня к другому вопросу: нужно ли мне закрывать и открывать (lua_open, lua_close) состояние Lua каждый раз, когда я вызываю функцию compile () с другими командами Lua, иначе вывод будет только результатом самая последняя luaL_loadstring?

Я не уверен, но посмотрите из определения макроса toproto, что вернется самый верхний стек, я прав?

1 Ответ

0 голосов
/ 05 мая 2012

Вы должны использовать lua_dump() вместо внутренних toproto() + luaU_dump() функций. В качестве дополнительного бонуса ваш код будет поддерживать LuaJIT 2 .

Нет необходимости воссоздавать состояние каждый раз, когда вы получаете дамп.

НО. Я бы не стал выполнять байт-код Lua, полученный из ненадежного источника (а сервер часто является ненадежным для клиента). Это небезопасно, и может привести к серьезным проблемам безопасности. (Таких проблем с исходным кодом нет, но, конечно, вам все равно придется его помещать в песочницу.)

В общем, всегда убедитесь, что вы проверяете, что код, который вы загружаете из ненадежного источника, не байт-код (если первый байт 27 десятичное число). Всегда выполнить такой код в песочнице .


Если все, что вам нужно, это передавать данные дружественным по отношению к Lua способом, выберите вместо этого подходящую библиотеку сериализации данных. Помимо проблем с песочницей и переносимостью, loadstring() довольно медленный.

Например, мы используем мою библиотеку luatexts для аналогичных целей (обязательно просмотрите этот список для альтернатив). Luatexts поддерживает кортежи, которые прекрасно работают с вызовами функций. Например (в псевдокоде):

Сервер:

my_send(luatexts.lua.save("myMethod", { param = true }, 42))

Клиент:

local actions = { }

function actions.myMethod(params, number)
  print(params.param, number) --> true, 42
end

local function handle_action(ok, name, ...)
  assert(ok, name) -- name would contain error message if not OK
  local handler = assert(actions[name], "unknown action")
  return handler(...)
end

local str = my_receive()

handle_action(luatexts.load(str))

Откройте тикет, если вы хотите luatexts.save или поддержку потоковой передачи, реализованную в C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...