mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
160 lines
3.6 KiB
C
160 lines
3.6 KiB
C
#include "skynet.h"
|
|
|
|
#include <lua.h>
|
|
#include <lualib.h>
|
|
#include <lauxlib.h>
|
|
#include <assert.h>
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
struct snlua {
|
|
lua_State * L;
|
|
struct skynet_context * ctx;
|
|
};
|
|
|
|
// LUA_CACHELIB may defined in patched lua for shared proto
|
|
#ifdef LUA_CACHELIB
|
|
|
|
#define codecache luaopen_cache
|
|
|
|
#else
|
|
|
|
static int
|
|
cleardummy(lua_State *L) {
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
codecache(lua_State *L) {
|
|
luaL_Reg l[] = {
|
|
{ "clear", cleardummy },
|
|
{ NULL, NULL },
|
|
};
|
|
luaL_newlib(L,l);
|
|
lua_getglobal(L, "loadfile");
|
|
lua_setfield(L, -2, "loadfile");
|
|
return 1;
|
|
}
|
|
|
|
#endif
|
|
|
|
static int
|
|
traceback (lua_State *L) {
|
|
const char *msg = lua_tostring(L, 1);
|
|
if (msg)
|
|
luaL_traceback(L, L, msg, 1);
|
|
else {
|
|
lua_pushliteral(L, "(no error message)");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
_report_launcher_error(struct skynet_context *ctx) {
|
|
// sizeof "ERROR" == 5
|
|
skynet_sendname(ctx, ".launcher", PTYPE_TEXT, 0, "ERROR", 5);
|
|
}
|
|
|
|
static const char *
|
|
optstring(struct skynet_context *ctx, const char *key, const char * str) {
|
|
const char * ret = skynet_command(ctx, "GETENV", key);
|
|
if (ret == NULL) {
|
|
return str;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
_init(struct snlua *l, struct skynet_context *ctx, const char * args, size_t sz) {
|
|
lua_State *L = l->L;
|
|
l->ctx = ctx;
|
|
lua_gc(L, LUA_GCSTOP, 0);
|
|
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
|
|
luaL_openlibs(L);
|
|
lua_pushlightuserdata(L, ctx);
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "skynet_context");
|
|
luaL_requiref(L, "skynet.codecache", codecache , 0);
|
|
lua_pop(L,1);
|
|
|
|
const char *path = optstring(ctx, "lua_path","./lualib/?.lua;./lualib/?/init.lua");
|
|
lua_pushstring(L, path);
|
|
lua_setglobal(L, "LUA_PATH");
|
|
const char *cpath = optstring(ctx, "lua_cpath","./luaclib/?.so");
|
|
lua_pushstring(L, cpath);
|
|
lua_setglobal(L, "LUA_CPATH");
|
|
const char *service = optstring(ctx, "luaservice", "./service/?.lua");
|
|
lua_pushstring(L, service);
|
|
lua_setglobal(L, "LUA_SERVICE");
|
|
const char *preload = skynet_command(ctx, "GETENV", "preload");
|
|
lua_pushstring(L, preload);
|
|
lua_setglobal(L, "LUA_PRELOAD");
|
|
|
|
lua_pushcfunction(L, traceback);
|
|
assert(lua_gettop(L) == 1);
|
|
|
|
const char * loader = optstring(ctx, "lualoader", "./lualib/loader.lua");
|
|
|
|
int r = luaL_loadfile(L,loader);
|
|
if (r != LUA_OK) {
|
|
skynet_error(ctx, "Can't load %s : %s", loader, lua_tostring(L, -1));
|
|
_report_launcher_error(ctx);
|
|
return 1;
|
|
}
|
|
lua_pushlstring(L, args, sz);
|
|
r = lua_pcall(L,1,0,1);
|
|
if (r != LUA_OK) {
|
|
skynet_error(ctx, "lua loader error : %s", lua_tostring(L, -1));
|
|
_report_launcher_error(ctx);
|
|
return 1;
|
|
}
|
|
lua_settop(L,0);
|
|
|
|
lua_gc(L, LUA_GCRESTART, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_launch(struct skynet_context * context, void *ud, int type, int session, uint32_t source , const void * msg, size_t sz) {
|
|
assert(type == 0 && session == 0);
|
|
struct snlua *l = ud;
|
|
skynet_callback(context, NULL, NULL);
|
|
int err = _init(l, context, msg, sz);
|
|
if (err) {
|
|
skynet_command(context, "EXIT", NULL);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) {
|
|
int sz = strlen(args);
|
|
char * tmp = skynet_malloc(sz);
|
|
memcpy(tmp, args, sz);
|
|
skynet_callback(ctx, l , _launch);
|
|
const char * self = skynet_command(ctx, "REG", NULL);
|
|
uint32_t handle_id = strtoul(self+1, NULL, 16);
|
|
// it must be first message
|
|
skynet_send(ctx, 0, handle_id, PTYPE_TAG_DONTCOPY,0, tmp, sz);
|
|
return 0;
|
|
}
|
|
|
|
struct snlua *
|
|
snlua_create(void) {
|
|
struct snlua * l = skynet_malloc(sizeof(*l));
|
|
memset(l,0,sizeof(*l));
|
|
l->L = lua_newstate(skynet_lalloc, NULL);
|
|
return l;
|
|
}
|
|
|
|
void
|
|
snlua_release(struct snlua *l) {
|
|
lua_close(l->L);
|
|
skynet_free(l);
|
|
}
|