我是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);
}
您无法注册模板功能。您必须注册显式实例。
#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);
}