Skip to content

[ -- additional -- ] Lambda and std::function #59

@DominikMS

Description

@DominikMS

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;
        }

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions