lua require DLL动态库,传入callback

上个Demo主要写了C++类的各种参数传入,然而这些参数并不包括函数,后面又改了部分,加入callback:


#include <iostream>

#include <functional>
using namespace std;
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "tolua/tolua++.h"
}
class Fish{
public:
	Fish() :_positionX(0), _positionY(0), _positionZ(0), _name("defaule"){ cout << "the name is " << _name.c_str() << endl; }
	~Fish(){};
	std::string getName(){ _callBack(); return _name; }
	void setCallBack(const std::function<void()>& callBack){ _callBack = callBack; }
	void setName(std::string name){ _name = name; }
private:
	std::string  _name;
	float _positionX;
	float _positionY;
	float _positionZ;
	std::function<void()> _callBack;

};
template <class T>
void object_to_luaval(lua_State* L, const char* type, T* ret)
{
	if (nullptr != ret)
	{
		tolua_pushusertype(L, (void*)ret, getLuaTypeName(ret, type));
	}
	else
	{
		lua_pushnil(L);
	}
}
// __declspec(dllexport)
static int ding_sum2(lua_State *L){
	double d1 = luaL_checknumber(L, 1);
	double d2 = luaL_checknumber(L, 2);
	lua_pushnumber(L, d1 + d2);
	return 1;
}

static const struct luaL_Reg global_lib[] = {
		{ "global_lib", ding_sum2 },
		{ NULL, NULL }
};

static int s_function_ref_id = 0;
int  lua_Fish_constructor(lua_State* L)//__cdecl
{
	Fish*  cobj = nullptr;
	cobj = new Fish();
	tolua_pushusertype_and_addtoroot(L, cobj, "Fish");
    return 1;
}

// check lua value is function
TOLUA_API int toluafix_isfunction(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
{
	if (lua_gettop(L) >= abs(lo) && lua_isfunction(L, lo))
	{
		return 1;
	}
	err->index = lo;
	err->array = 0;
	err->type = "[not function]";
	return 0;
}
bool luaval_to_std_string(lua_State* L, int lo, std::string* outValue, const char* funcName)
{
	if (NULL == L || NULL == outValue)
		return false;
	bool ok = true;
	tolua_Error tolua_err;
	if (!tolua_iscppstring(L, lo, 0, &tolua_err))
	{
		ok = false;
	}
	if (ok)
	{
		size_t size;
		auto rawString = lua_tolstring(L, lo, &size);
		*outValue = std::string(rawString, size);
	}
	return ok;
}

TOLUA_API int toluafix_ref_function(lua_State* L, int lo, int def)
{
	// function at lo
	if (!lua_isfunction(L, lo)) return 0;

	s_function_ref_id++;
	int top = lua_gettop(L);
	

	//lua_newtable(L);
	lua_pushstring(L, "toluafix_refid_function_mapping");
	
	lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: fun ... refid_fun */
	//lua_newtable(L);
	lua_pushinteger(L, s_function_ref_id);                      /* stack: fun ... refid_fun refid */
	lua_pushvalue(L, lo);                                       /* stack: fun ... refid_fun refid fun */

	lua_rawset(L, -3);                  /* refid_fun[refid] = fun, stack: fun ... refid_ptr */
	lua_pop(L, 1);                                              /* stack: fun ... */

	return s_function_ref_id;
	//return s_function_ref_id;

	// lua_pushvalue(L, lo);                                           /* stack: ... func */
	// return luaL_ref(L, LUA_REGISTRYINDEX);
}
TOLUA_API void toluafix_get_function_by_refid(lua_State* L, int refid)
{
	lua_pushstring(L, "toluafix_refid_function_mapping");
	lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: ... refid_fun */
	lua_pushinteger(L, refid);                                  /* stack: ... refid_fun refid */
	lua_rawget(L, -2);                                          /* stack: ... refid_fun fun */
	lua_remove(L, -2);                                          /* stack: ... fun */
}
bool pushFunctionByHandler(lua_State* L, int nHandler)
{
	toluafix_get_function_by_refid(L, nHandler);                  /* L: ... func */
	if (!lua_isfunction(L, -1))
	{
		//CCLOG("[LUA ERROR] function refid '%d' does not reference a Lua function", nHandler);
		lua_pop(L, 1);
		return false;
	}
	return true;
}
int executeFunction(lua_State* L,int numArgs)
{
	int functionIndex = -(numArgs + 1);
	if (!lua_isfunction(L, functionIndex))
	{
		//CCLOG("value at stack [%d] is not function", functionIndex);
		lua_pop(L, numArgs + 1); // remove function and arguments
		return 0;
	}

	int traceback = 0;
	lua_getglobal(L, "__G__TRACKBACK__");                         /* L: ... func arg1 arg2 ... G */
	if (!lua_isfunction(L, -1))
	{
		lua_pop(L, 1);                                            /* L: ... func arg1 arg2 ... */
	}
	else
	{
		lua_insert(L, functionIndex - 1);                         /* L: ... G func arg1 arg2 ... */
		traceback = functionIndex - 1;
	}

	int error = 0;
	//++_callFromLua;
	error = lua_pcall(L, numArgs, 1, traceback);                  /* L: ... [G] ret */
	//callFromLua;
	if (error)
	{
		if (traceback == 0)
		{
		//	CCLOG("[LUA ERROR] %s", lua_tostring(_state, -1));        /* L: ... error */
			lua_pop(L, 1); // remove error message from stack
		}
		else                                                            /* L: ... G error */
		{
			lua_pop(L, 2); // remove __G__TRACKBACK__ and error message from stack
		}
		return 0;
	}

	// get return value
	int ret = 0;
	if (lua_isnumber(L, -1))
	{
		ret = (int)lua_tointeger(L, -1);
	}
	else if (lua_isboolean(L, -1))
	{
		ret = (int)lua_toboolean(L, -1);
	}
	// remove return value from stack
	lua_pop(L, 1);                                                /* L: ... [G] */

	if (traceback)
	{
		lua_pop(L, 1); // remove __G__TRACKBACK__ from stack      /* L: ... */
	}

	return ret;
}
int executeFunctionByHandler(lua_State* L,int nHandler, int numArgs)
{
	int ret = 0;
	if (pushFunctionByHandler(L,nHandler))                                /* L: ... arg1 arg2 ... func */
	{
		if (numArgs > 0)
		{
			lua_insert(L, -(numArgs + 1));                        /* L: ... func arg1 arg2 ... */
		}
		ret = executeFunction(L,numArgs);
	}
	lua_settop(L, 0);
	return ret;
}

int  lua_Fish_Set_Name(lua_State* L)//__cdecl
{
	int argc = 0;
	Fish*  cobj = nullptr;
	tolua_Error tolua_err;
	bool ok = true;
	if (!tolua_isusertype(L, 1, "Fish", 0, &tolua_err)) goto tolua_lerror;

	cobj = (Fish*)tolua_tousertype(L, 1, 0);
	
	if (!cobj)
	{
		tolua_error(L, "invalid 'cobj' in function 'lua_Fish_Set_Name'", nullptr);
		return 0;
	}
	argc = lua_gettop(L) - 1;
	if (argc == 1)
	{
		std::string arg0;

		ok &= luaval_to_std_string(L, 2, &arg0, "Fish:setName");
		if (!ok)
		{
			tolua_error(L, "invalid arguments in function 'lua_Fish_Set_Name'", nullptr);
			return 0;
		}
		cobj->setName(arg0);
		lua_settop(L, 1);
		return 1;
	}
tolua_lerror:
	tolua_error(L, "#ferror in function 'lua_Fish_Set_Name'.", &tolua_err);
	return 1;
}


int lua_Fish_set_callBack(lua_State* L)
{
	if (L == NULL)
		return 0;
	int argc = 0;
	Fish*  cobj = nullptr;
	tolua_Error tolua_err;
	bool ok = true;
	if (!tolua_isusertype(L, 1, "Fish", 0, &tolua_err)) goto tolua_lerror;
	cobj = (Fish*)tolua_tousertype(L, 1, 0);

	if (!cobj)
	{
		tolua_error(L, "invalid 'cobj' in function 'lua_Fish_set_callBack'", nullptr);
		return 0;
	}
	argc = lua_gettop(L) - 1;
	do {
		if (argc == 1)
		{
			if (!toluafix_isfunction(L, 2, "LUA_FUNCTION", 0, &tolua_err)) {
				goto tolua_lerror;
			}
			
			
			int handler = toluafix_ref_function(L, 2, 0);
			cout << "handler is " << handler<< endl;
			cobj->setCallBack([=](){
				cout << "do the callBak" << handler<< endl;
				executeFunctionByHandler(L, handler, 1);
			});
			//toluafix_pushusertype_ccobject(L, id, luaID, (void*)sprite, "cc.Sprite3D");



			//cobj->setName(arg0);
			lua_settop(L, 1);
			return 1;
		}
	} while (0);
	
tolua_lerror:
	tolua_error(L, "#ferror in function 'lua_Fish_Set_Name'.", &tolua_err);
	return 1;
}
int  lua_Fish_Get_Name(lua_State* L)//__cdecl
{
	int argc = 0;
	Fish*  cobj = nullptr;
	bool ok = true;
	tolua_Error tolua_err;
	if (!tolua_isusertype(L, 1, "Fish", 0, &tolua_err)) goto tolua_lerror;
	cobj = (Fish*)tolua_tousertype(L, 1, 0);
	if (!cobj)
	{
		tolua_error(L, "invalid 'cobj' in function 'lua_cocos2dx_Node_getChildByName'", nullptr);
		return 0;
	}

	argc = lua_gettop(L) - 1;
	if (argc == 0)
	{
		std::string arg0;
		std::string ret = cobj->getName();
		lua_pushlstring(L, ret.c_str(), ret.length());
		return 1;
	}
	luaL_error(L, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Node:getChildByName", argc, 1);
	return 0;
	

tolua_lerror:
	tolua_error(L, "#ferror in function 'lua_cocos2dx_Node_getChildByName'.", &tolua_err);

	return 0;
}

extern "C" {
	int __declspec(dllexport)  luaopen_fish(lua_State *L){

		//luaL_newlib(L, ding_lib); // 5.2
		//L = lua_open();
		luaL_openlibs(L);
		lua_pushstring(L, "toluafix_refid_function_mapping");
		lua_newtable(L);
		lua_rawset(L, LUA_REGISTRYINDEX);
		tolua_open(L);


#ifndef Mtolua_typeid
#define Mtolua_typeid(L,TI,T)
#endif
		tolua_usertype(L, "Fish");
		Mtolua_typeid(L, typeid(CCSprite), "Fish");
		tolua_open(L);
		tolua_module(L, nullptr, 0);
		tolua_beginmodule(L, nullptr);
		//tolua_usertype(L, "Fish");
		tolua_cclass(L, "Fish", "Fish", "", nullptr);
		tolua_beginmodule(L, "Fish");
		tolua_function(L, "new", lua_Fish_constructor);
		tolua_function(L, "getName", lua_Fish_Get_Name);
		tolua_function(L, "setName", lua_Fish_Set_Name);
		tolua_function(L, "setCallBack", lua_Fish_set_callBack);
		
		tolua_endmodule(L);
		tolua_endmodule(L);
		luaL_register(L, "global_lib", global_lib); // lua 5.1

		return 1;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值