-
Notifications
You must be signed in to change notification settings - Fork 20
Open
Labels
Description
Example:
g_lua.
Class<ClassTest>("ClassTest").
method("emptyRet", std::function<void(int)>([](int x)
{
std::cout << "[hello void std::function] " << x << std::endl;
} )).
method("boolRet", std::function<bool(int)>([](int x)
{
std::cout << "[hello return std::function] " << x << std::endl;
return true;
} )).
method("lambda", [](int x) { std::cout << "[hello lambda]" << std::endl; return true; } );
g_lua.func("getBoolTest", std::function<bool(int x)>( [](){ return true; } ));
Todo:
[Fixed] Can't bind std::function under LuaGlue.func()
[Fixed] Can't bind and lambda under LuaGlue.func()
Code:
Add file: LuaGlueStdFuncMethod.h
#ifndef LUAGLUE_STDFUNC_METHOD_H_GUARD
#define LUAGLUE_STDFUNC_METHOD_H_GUARD
#include <string>
#include <tuple>
#include <utility>
#include "LuaGlue/LuaGlueObject.h"
#include "LuaGlue/LuaGlueApplyTuple.h"
#include "LuaGlue/LuaGlueBase.h"
template<typename _Class>
class LuaGlueClass;
class LuaGlueMethodBase;
template<typename _Ret, typename _Class, typename... _Args>
class LuaGlueStdFuncMethod : public LuaGlueMethodBase
{
private:
typedef std::tuple<typename std::remove_const<typename std::remove_reference<_Args>::type>::type...> ArgsTuple;
typedef _Class ClassType;
typedef _Ret ReturnType;
typedef std::function<_Ret(_Args...)> MethodType;
LuaGlueClass<_Class> *glueClass;
std::string name_;
MethodType fn;
ArgsTuple args;
static const unsigned int Arg_Count_ = sizeof...(_Args);
public:
LuaGlueStdFuncMethod(LuaGlueClass<_Class> *luaClass, const std::string &name, MethodType &&fn) :
glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn))
{ }
virtual ~LuaGlueStdFuncMethod() { }
virtual bool glue(LuaGlueBase *luaGlue)
{
lua_pushlightuserdata(luaGlue->state(), this);
lua_pushcclosure(luaGlue->state(), &lua_call_func, 1);
lua_setfield(luaGlue->state(), -2, name_.c_str());
return true;
}
static int lua_call_func(lua_State *state)
{
auto mimp = (LuaGlueStdFuncMethod<_Ret, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1));
return mimp->invoke(state);
}
int invoke(lua_State *state)
{
ReturnType ret = applyTuple<_Ret, _Args...>(glueClass->luaGlue(), state, fn, args);
lua_pop(state, (int)Arg_Count_);
stack<_Ret>::put(glueClass->luaGlue(), state, ret);
return 1;
}
};
template<typename _Class, typename... _Args>
class LuaGlueStdFuncMethod<void, _Class, _Args...> : public LuaGlueMethodBase
{
private:
typedef std::tuple<typename std::remove_const<typename std::remove_reference<_Args>::type>::type...> ArgsTuple;
typedef _Class ClassType;
typedef std::function<void(_Args...)> MethodType;
LuaGlueClass<_Class> *glueClass;
std::string name_;
MethodType fn;
ArgsTuple args;
static const unsigned int Arg_Count_ = sizeof...(_Args);
public:
LuaGlueStdFuncMethod(LuaGlueClass<_Class> *luaClass, const std::string &name, MethodType &&fn) :
glueClass(luaClass), name_(name), fn(std::forward<decltype(fn)>(fn))
{ }
virtual ~LuaGlueStdFuncMethod() { }
virtual bool glue(LuaGlueBase *luaGlue)
{
lua_pushlightuserdata(luaGlue->state(), this);
lua_pushcclosure(luaGlue->state(), &lua_call_func, 1);
lua_setfield(luaGlue->state(), -2, name_.c_str());
return true;
}
static int lua_call_func(lua_State *state)
{
auto mimp = (LuaGlueStdFuncMethod<void, _Class, _Args...> *)lua_touserdata(state, lua_upvalueindex(1));
return mimp->invoke(state);
}
int invoke(lua_State *state)
{
applyTuple<void, _Args...>(glueClass->luaGlue(), state, fn, args);
lua_pop(state, (int)Arg_Count_);
return 0;
}
};
#endif /* LUAGLUE_STDFUNC_METHOD_H_GUARD */
Edit file: LuaGluaClass.h
// std::function and lambda method
template<typename _Ret, typename... _Args>
LuaGlueClass<_Class> &method(const std::string &name, std::function<_Ret(_Args...)> fn)
{
auto impl = new LuaGlueStdFuncMethod<_Ret, _Class, _Args...>(this, name, std::forward<decltype(fn)>(fn));
methods.addSymbol(name.c_str(), impl);
return *this;
}
template<typename F>
struct BindLambda;
template<typename Lambda, typename Ret, typename... Args>
struct BindLambda<Ret(Lambda::*)(Args...) const>
{
static std::function<Ret(const Args...)> call(const Lambda& lambda)
{
return std::function<Ret(Args...)>(lambda);
}
};
template<typename Lambda>
LuaGlueClass<_Class> &method(const std::string &name, const Lambda& lambda)
{
typedef decltype(&Lambda::operator()) F;
method(name, BindLambda<F>::call(lambda));
return *this;
}
// end std::function and lambda method
Fix:
Edit LuaGluFunction.h[142]
ReturnType ret = applyTuple(g, state, fn_, args);
Edit LuaGluFunction.h[157]
auto mimp = (LuaGlueFunction<std::function<_Ret(_Args...)>> *)lua_touserdata(state, lua_upvalueindex(1));
Edit LuaGluFunction.h[191]
applyTuple<void, _Args...>(g, state, fn_, args);
Add LuaGlue.h
//--- std::function ---//
template<typename Ret_, typename... Args_>
LuaGlue &func(const std::string &name, std::function<Ret_(Args_...)> fn)
{
auto new_func = new LuaGlueFunction<std::function<Ret_(Args_...)>>(this, name, fn);
functions.addSymbol(name.c_str(), new_func);
return *this;
}
//--- Lambda ---//
template<typename F>
struct BindLambda;
template<typename Lambda, typename Ret, typename... Args>
struct BindLambda<Ret(Lambda::*)(Args...) const>
{
static std::function<Ret(Args...)> call(const Lambda& lambda)
{
return std::function<Ret(Args...)>(lambda);
}
};
template<typename Lambda>
LuaGlue &func(const std::string &name, const Lambda& lambda)
{
typedef decltype(&Lambda::operator()) F;
func(name, BindLambda<F>::call(lambda));
return *this;
}