c++調用lua註冊的帶參數的回調

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<void(const TcpSessionPtr &  /*session*/, const char * /*begin*/, unsigned int /*len*/)>;
using OnSessionEvent = std::function<void(const TcpSessionPtr &  /*session*/)>;

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章