将Lua脚本编译为unsigned char缓冲区

时间:2012-03-05 05:42:15

标签: c lua

我在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命令调用我的compile()函数时,是否必须关闭并重新打开(lua_open,lua_close)Lua状态,否则输出只会是最新的luaL_loadstring?

我不确定,但是从toproto宏定义中看到我将返回最顶层的堆栈,我是否正确?

1 个答案:

答案 0 :(得分:0)

您应该使用lua_dump()而不是内部toproto() + luaU_dump()功能。作为额外的好处,这样您的代码将支持LuaJIT 2

每次获得转储时都没有必要重新创建状态。

BUT。我会避免执行来自不受信任来源的Lua字节码(而且服务器经常 不受信任到客户端)。 不安全,,可能会导致严重的安全问题。 (源代码没有这样的问题 - 当然,你仍然必须对它进行沙盒化。)

通常,总是确保您检查从不受信任的源加载的代码是不是字节码(如果是byte是27十进制的)。 始终执行此类代码in a sandbox


如果您只需要以Lua友好的方式传递数据,请选择一些正确的数据序列化库。除沙箱和可移植性问题外,loadstring()相当慢。

例如,我们正在使用我的luatexts库进行类似的目的(确保通过this list填充替代品)。 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或流媒体支持,请打开故障单。