Как зарегистрировать шаблонную функцию в LuaBridge?
Я новичок в Lua и LuaBridge и пытаюсь выяснить, можно ли зарегистрировать шаблонную функцию? Я посмотрел в Интернете и через руководство LuaBridge безрезультатно. Я попытался создать указатель на базовый класс, но потом выяснил, что в Lua нет способа привести его в действие. Если у кого-то есть какие-либо идеи о том, как решить эту проблему, мы будем благодарны.
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();
}
Решение
Забыл опубликовать это ранее, но решение состоит в том, чтобы определить тип из строки, оттуда вам нужно установить глобальный в Lua, а затем вернуть ссылку на этот глобальный.
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);
}
1 ответ
Вы не можете зарегистрировать шаблонную функцию. Вы должны зарегистрировать явные экземпляры.
#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';
}
Я бы предложил вам использовать sol2, который не имеет такого ужасного синтаксиса (хотя нужен C++14).
#include <iostream>
#include <string>
#include <sol.hpp>
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()
{
sol::state L;
L.open_libraries();
L.new_usertype<Test>("Test",
"test_int", &Test::test<int>,
"test_str", &Test::test<std::string>
);
L.script(script);
}