How do I register a templated function with LuaBridge?

I'm new to Lua and LuaBridge and I am trying to figure out if it is possible to register a templated function? I looked online and through the LuaBridge manual to no avail. I tried to create a pointer to the base class, but then I found out later that there is no way to insert it in Lua. If anyone has any ideas on the best way to tackle this problem it would be appreciated.

template<typename T>
T* GetComponentByType()
{
    try
    {
        for (ComponentVectorWrapper::t_Component_Iter iter = m_Components_.begin(); iter != m_Components_.end(); ++iter)
            if (*iter != nullptr)
                if (T* type = dynamic_cast<T*>(*iter))
                    return type;
        throw ComponentMissingException();
    }
    catch (ComponentMissingException& e)
    {
        std::cout << e.what() << std::endl;
        __debugbreak();
    }
}

Component* getComponentByType(std::string type)
{
    if (type == "Transform")
        return GetComponentByType<TransformComponent>();

    return nullptr;
}

static void registerLua(lua_State* L)
{
    using namespace luabridge;

    getGlobalNamespace(L)
        .beginClass<GameObject>("GameObject")
        .addConstructor<void(*)(const char* name)>()
        .addData<const char*>("name", &GameObject::m_Name_, false)
        .addData<TransformComponent*>("transform", &GameObject::m_Transform)
        .addFunction("addComponent", &GameObject::registerComponent)
        .addFunction("getComponent", &GameObject::getComponentByType)
        .addFunction("removeComponent", &GameObject::removeComponent)
        .endClass();
}

      

Decision

Forgot to post this earlier, but the solution is to determine the type from the string, from there you need to set a global value in Lua and then return a reference to that global.

luabridge::LuaRef GameObject::luaGetComponent(std::string type)
{
    // Return component
    return luaGetComponentHelper(type, false, "");
}

luabridge::LuaRef GameObject::luaGetComponentHelper(std::string type, bool findAll, const char* tag)
{
    lua_State* L = (&LuaEngine::getInstance())->L();

    // Find component type
    if (type == "TransformComponent")
        LuaHelper::GetGlobalComponent<TransformComponent>(*this, findAll, m_CompName, tag);
    else if (type == "CameraComponent")
        LuaHelper::GetGlobalComponent<CameraComponent>(*this, findAll, m_CompName, tag);
    else if (type == "FirstPersonCameraComponent")
        LuaHelper::GetGlobalComponent<FirstPersonCameraComponent>(*this, findAll, m_CompName, tag);
    else if (type == "RenderComponent")
        LuaHelper::GetGlobalComponent<RenderComponent>(*this, findAll, m_CompName, tag);
    else if (type == "ThirdPersonCameraComponent")
        LuaHelper::GetGlobalComponent<ThirdPersonCameraComponent>(*this, findAll, m_CompName, tag);
    else if (type == "CanvasComponent")
        LuaHelper::GetGlobalComponent<CanvasComponent>(*this, findAll, m_CompName, tag);
    else if (type == "RigidBody")
        LuaHelper::GetGlobalComponent<RigidBody>(*this, findAll, m_CompName, tag);
    else if (type == "BoxCollider")
        LuaHelper::GetGlobalComponent<BoxCollider>(*this, findAll, m_CompName, tag);
    else
    {
        luabridge::setGlobal(L, nullptr, m_CompName); // Prevents errors
        LuaEngine::printError("Component not found.");
    }

    // Return component
    return luabridge::getGlobal(L, m_CompName);
}

template<typename T>
static luabridge::LuaRef GetGlobalComponent(GameObject& go, bool findAll, const char* globalName, const char* tag)
{
    // Get lua state
    auto L = LuaEngine::getInstance().L();

    // Register global
    if (findAll)
    {
        auto vec = go.GetComponentsByType<T>();
        // Check for tag
        if (tag != "")
        {
            // Find by tag
            std::vector<T*> elements;

            for (auto& e : vec)
            {
                if (static_cast<Component*>(e)->getTag() == tag)
                    elements.push_back(e);
            }

            luabridge::setGlobal(L, LuaHelper::ToTable(elements), globalName);
        }
        else
            luabridge::setGlobal(L, LuaHelper::ToTable(vec), globalName);
    }
    else
        luabridge::setGlobal(L, go.GetComponentByType<T>(), globalName);

    return luabridge::getGlobal(L, globalName);
}

      

+3


source to share


1 answer


You cannot register a templated function. You must register explicit instances.

#include <iostream>
#include <lua.hpp>
#include <LuaBridge.h>

char const script [] =
  "local t = Test()"
  "t:test_int(123)"
  "t:test_str('Hello')";

class Test
{
public:
  template < typename T >
  void test(T t) { std::cout << t << '\n'; }
};

int main()
{
  lua_State* L = luaL_newstate();
  luaL_openlibs(L);

  luabridge::getGlobalNamespace(L)
    .beginClass<Test>("Test")
      .addConstructor<void(*)(void)>()
      .addFunction("test_int", &Test::test<int>)
      .addFunction("test_str", &Test::test<char const *>)
    .endClass();

  if ( luaL_dostring(L, script) != 0)
    std::cerr << lua_tostring(L,-1) << '\n';
}

      




I suggest you use Selene , which doesn't have such awful syntax (C ++ 11 required).

#include <iostream>
#include <string>
#include <selene.h>

char const script [] =
  "local t = Test.new()"
  "t:test_int(123)"
  "t:test_str('Hello')";

class Test
{
public:
  template < typename T >
  void test(T t) { std::cout << t << '\n'; }
};

int main()
{
  sel::State L{true};

  L["Test"].SetClass<Test>(
    "test_int", &Test::test<int>,
    "test_str", &Test::test<std::string>
    );

  L(script);
}

      

+1


source







All Articles