1.luaL_ref
原型:
int luaL_ref (lua_State *L, int t);
该方法对栈顶对象创建一个引用,放在table的index里,这里的index就是参数t,记住这个t,在用rawgeti是会用到。引用是唯一的
2.lua_rawgeti
原型:
void lua_rawgeti (lua_State *L, int index, int n);
把t[n]的值压栈,index就是luaL_ref中的t,n就是key,比如一些方法,这是一个直接访问,不会触发元方法
lua_State.NewTable()
ref = lua_State.luaL_ref( index )
lua_State.lua_rawgeti(index,ref )
以上是伪代码,大意就是先创建Table,设置引用ref,在直接取得table
main.cpp
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
using OnBlockDispatch = std::function;
using OnSessionEvent = std::function;
struct AccepterOptions
{
int _aID = InvalidAccepterID;
std::string _listenIP;
unsigned short _listenPort = 0;
unsigned int _maxSessions = 10000;
int _protoType = 0;
unsigned int _sessionPulseInterval = 30000;
std::string _rc4TcpEncryption = ""; //empty is not encryption
OnBlockDispatch _onBlockDispatch;
OnSessionEvent _onSessionLinked;
};
static void _onSessionLinked(lua_State * L, int linkedRef, std::string ip, int port)
{
if (linkedRef == LUA_NOREF)
{
LOGE("_onSessionLinked error: cannot found ther callback.");
return;
}
lua_pushcfunction(L, pcall_error);
lua_rawgeti(L, LUA_REGISTRYINDEX, linkedRef);
lua_pushstring(L, ip.c_str());
lua_pushnumber(L, port);
int status = lua_pcall(L, 2, 0, 1);
lua_remove(L, 1);
if (status)
{
const char *msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error object is not a string)";
LOGE(msg);
lua_pop(L, 1);
}
}
//param:sID, pID, content
static void _onMessage(lua_State * L, int messageRef, const char * begin, unsigned int len)
{
if (messageRef == LUA_NOREF)
{
LOGE("_onMessage error: cannot found ther callback.");
return;
}
ReadStream rs(begin, len);
lua_pushcfunction(L, pcall_error);
lua_rawgeti(L, LUA_REGISTRYINDEX, messageRef);
lua_pushlstring(L, begin, len);
int status = lua_pcall(L, 1, 0, 1);
lua_remove(L, 1);
if (status)
{
const char *msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error object is not a string)";
LOGE("code crash when process message. sID=" << session->getSessionID() << ", block len=" << len
<< ", block=" << log4z::Log4zBinary(begin, len));
LOGE(msg);
lua_pop(L, 1);
}
}
//1.ip 2.port 3.encrypt string 4.max Session 5.pulse int(ms) 6.proto type(0 tcp, 1 http) 7.link_fun 8.msg_fun 9.web_msg_fun 10.close_fun 11.pause_fun
static int addListen(lua_State *L)
{
AccepterOptions extend;
extend._listenIP = luaL_checkstring(L, 1);
extend._listenPort = luaL_checkstring(L, 2);
extend._sessionOptions._rc4TcpEncryption = luaL_optstring(L, 3, extend._rc4TcpEncryption.c_str());
extend._maxSessions = (unsigned int)luaL_optinteger(L, 4, extend._maxSessions);
extend._sessionPulseInterval = (unsigned int)luaL_optinteger(L, 5, extend._sessionPulseInterval);
extend._protoType = (unsigned int)luaL_optinteger(L, 6, 0) == 0 ? PT_TCP : PT_HTTP;
luaL_checktype(L, 7, LUA_TFUNCTION);
lua_pushvalue(L, 7);
int linkedRef = luaL_ref(L, LUA_REGISTRYINDEX);
luaL_checktype(L, 8, LUA_TFUNCTION);
lua_pushvalue(L, 8);
int messageRef = luaL_ref(L, LUA_REGISTRYINDEX);
extend._onSessionLinked = std::bind(_onSessionLinked, L, linkedRef, std::placeholders::_1);
extend._onBlockDispatch = std::bind(_onMessage, L, messageRef, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
//LOGD("lua: addListen:" << extend);
if (!SessionManager::getRef().openAccepter(aID))
{
return 0;
}
lua_pushnumber(L, aID);
return 1;
}
static luaL_Reg lua_server[] = {
{ "addListen", addListen }, //add listen. param: 1.ip 2.port 3.encrypt string 4.max Session 5.pulse int(ms) 6.proto type(0 tcp, 1 http) 7.link_fun 8.msg_fun
{ "luaFunTest", luaFunTest },
{ NULL, NULL }
};
int luaopen_server(lua_State *L)
{
lua_newtable(L);
for (luaL_Reg *l = lua_server; l->name != NULL; l++) {
lua_pushcclosure(L, l->func, 0); /* closure with those upvalues */
lua_setfield(L, -2, l->name);
}
lua_setglobal(L, "server");
return 0;
}
int safedofile(lua_State * L, const char * file)
{
int index = lua_gettop(L);
lua_pushcfunction(L, pcall_error);
int status = luaL_loadfile(L, file) || lua_pcall(L, 0, 0, index + 1);
lua_remove(L, index + 1);
return status;
}
int main(int argc, char* arge[])
{
ILog4zManager::getRef().start();
//ILog4zManager::getRef().setLoggerFileLine(LOG4Z_MAIN_LOGGER_ID, false);
int status;
lua_State *L = luaL_newstate(); /* create state */
if (L == NULL)
{
return EXIT_FAILURE;
}
lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
luaL_openlibs(L);
luaopen_server(L);
lua_gc(L, LUA_GCRESTART, 0);
status = safedofile(L, "./mian.lua");
if (status)
{
const char *msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error object is not a string)";
LOGE(msg);
lua_pop(L, 1);
}
lua_close(L);
return (status) ? EXIT_FAILURE : EXIT_SUCCESS;
}
lua函数可以传递多个参数到c++函数,包含lua函数,lua数据类型,lua的table
test.lua
package.path = "../common/?.lua;./common/?/init.lua;./?.lua" .. package.path
local pairs , require,string = pairs , require ,string
local server = server
--require("server")
local lastTime = os.time()
local function luafun( value )
print("lua luafun value="..value)
end
local function onLink(ip, port)
print("lua onLink ip="..ip.." port="..port)
end
local function onMessage( msgId, msgContent)
print("lua onMessage content="..msgContent)
end
--服务器监听
--1.ip 2.port 3.encrypt string 4.max Session 5.pulse int(ms) 6.proto type(0 tcp, 1 http) 7.link_fun 8.msg_fun
local id = server.addListen("192.168.16.200",12008,'',10000,5000,0,onLink,onMessage)
if id == nil then
print("id == nil when addListen")
end
print("服务器运行结束")
代码有删减,原来基本是这样有问题可以加qq探讨 四七二四四二88期
参考:https://www.cnblogs.com/afan/p/6245871.html
https://blog.csdn.net/yuxikuo_1/article/details/52185370