gpt4 book ai didi

c++ - 使用 C++ 的自动 Lua 绑定(bind)

转载 作者:行者123 更新时间:2023-12-03 12:13:36 26 4
gpt4 key购买 nike

我正在构建一个简单的 2D 游戏引擎,它变得越来越大,在 Lua 中公开所有功能是不可能的:所以我试图自动化一点这个过程,
无论如何,是否可以一次从堆栈中获取所有 n 个参数(具有不同类型)并将它们直接注入(inject) C++ 函数。
我已经自动化了函数参数检查。仍然是有点棘手的函数绑定(bind)

例如:
我有更改 Sprite 位置的正常代码:

int LuaSprite::SetSpritePosition(lua_State* L)
{
Drawable* sprt = (Drawable*)lua_touserdata(L, 1);
int x = (int)lua_tonumber(L, 2);
int y = (int)lua_tonumber(L, 3);
sprt->setPosition(Vec2i(x, y));
return 0;
}

我想要实现的概念更像是这样的:
int LuaSprite::SetSpritePosition(lua_State* L)
{
LOAD_ARGS(Sprite*, int, int)
GET_ARG(1)->setPosition(Vec2i(GET_ARGS_FROM(1)));
LOAD_RETURN(true, x, y, 3);
return 3;
}

所以
  • LOAD_ARGS 将从堆栈中分别获取给定的类型。
  • GET_ARG(i) 将在索引 i 处获取 arg。
  • GET_ARGS_FROM(i) 会做这样的事情 x,y,z,type

  • 我没有要求相同的行为,因为它可能是不可能的,但至少是类似的
    而且我确信这仅使用“普通”C++ 是无法实现的,而且我还需要一些“魔术”宏。
    我没有使用现成的自动 Lua 绑定(bind)“库”,因为有自定义结构并且某些函数正在使用复杂的结构和类
    我做了很多搜索,我感到非常迷茫。

    最佳答案

    我找到了Luabridge在执行这些任务时非常方便。它是一个仅适用于较旧 C++ 代码(c++11 之前及之后)的 header 库。

    您不直接针对 Lua 堆栈进行编程,而是将普通类/结构包装到绑定(bind)定义中。

    绑定(bind)代码如下所示:

     getGlobalNamespace(L).beginNamespace("GameFrameworkName")

    .beginClass<RectF>("Rect")
    .addStaticFunction("__call", &RectF_Ctor) // Constructor from Table!
    .addData<float>("x", &RectF::x)
    .addData<float>("y", &RectF::y)
    .addData<float>("width", &RectF::width)
    .addData<float>("height", &RectF::height)
    .addFunction("Union", &RectF::Union)
    .addFunction("Intersects", (bool (RectF::*)(const RectF&)) &RectF::Intersects)
    .addFunction("Intersection", &RectF::Intersection)
    .addFunction("Contains", (bool (RectF::*)(const PointF&)) &RectF::Contains)
    .addFunction("Offset", (void (RectF::*)(const PointF&)) &RectF::Offset)
    .addFunction("Inflate", (void (RectF::*)(float, float)) &RectF::Inflate)
    .addFunction("__tostring", &RectF_ToString)
    .addFunction("__eq", (bool (RectF::*)(const RectF&)) &RectF::operator==)
    .addFunction("Copy", &RectF_Copy)
    .endClass()


    .beginClass<PointF>("Point")
    .addStaticFunction("__call", &PointF_Ctor) // Constructor from Table!
    .addData<float>("x", &PointF::x)
    .addData<float>("y", &PointF::y)
    .addFunction("__tostring", &PointF_ToString)
    .addFunction("__add", (PointF (PointF::*)(const PointF&)) &PointF::operator+ )
    .addFunction("__sub", &PointF_SubtractOperator )
    .addFunction("__mul", &PointF_MultiplyOperator )
    .addFunction("__div", &PointF_DivideOperator )
    .addFunction("__eq", (bool (PointF::*)(const PointF&)) &PointF::operator==)
    .addFunction("__unm", &PointF_Unm)
    .addFunction("Copy", &PointF_Copy)
    .endClass()

    .endNamespace();

    对于游戏对象,我通常会在 C++ 中管理生命周期,并将指针传递给 Lua。 Luabind 允许您覆盖 Lua CTor (__call) 和 ~Tor (__gc)。这是我的拷贝:
    template<typename T>
    std::string DoNotCreate()
    {
    DBG_ASSERT(false); // Do not try to create a new instance of this type
    return StrFormat("ERROR: Lua cannot create an instance of %s.", typeid(T).name());
    }


    ///////////////////////////////////////
    // \brief Do Not Allow Lua or Luabridge to delete us
    void DoNotGarbageCollect(void*) {}

    以及它们的用途:
    .deriveClass<Sprite, DisplayObject>("Sprite")
    .addStaticFunction("__call", &DoNotCreate<Sprite>)
    .addFunction("__gc", (void (*) (Sprite*)) &DoNotGarbageCollect)

    要从 C++ 调用 Lua 代码,您可以使用 LuaRefs,它 (IIRC) 基本上是可以是任何 Lua 类型的变体。

    如果你有兴趣,我找到了 Zerobrane要成为一个好的调试器,你只需要添加套接字 lua 库

    关于c++ - 使用 C++ 的自动 Lua 绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52564364/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com