- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我是 Bitfighter 的开发主管,我们正在混合使用 Lua 和 C++,使用 Lunar(Luna 的变体,可用 here)将它们绑定(bind)在一起。
我知道这个环境对面向对象和继承没有很好的支持,但我想找到一些方法来至少部分地解决这些限制。
这是我所拥有的:
C++ 类结构
GameItem |---- Rock |---- Stone |---- RockyStone Robot
Robot implements a method called getFiringSolution(GameItem item) that looks at the position and speed of item, and returns the angle at which the robot would need to fire to hit item.
-- This is in Lua
angle = robot:getFiringSolution(rock)
if(angle != nil) then
robot:fire(angle)
end
所以我的问题是我想将 rocks、stones 或 rockyStones 传递给 getFiringSolution 方法,但我不确定怎么做。
这只适用于 Rocks:
// C++ code
S32 Robot::getFiringSolution(lua_State *L)
{
Rock *target = Lunar<Rock>::check(L, 1);
return returnFloat(L, getFireAngle(target)); // returnFloat() is my func
}
理想情况下,我想做的是这样的:
// This is C++, doesn't work
S32 Robot::getFiringSolution(lua_State *L)
{
GameItem *target = Lunar<GameItem>::check(L, 1);
return returnFloat(L, getFireAngle(target));
}
这个潜在的解决方案不起作用,因为 Lunar 的检查函数希望堆栈上的对象具有与为 GameItem 定义的类名相匹配的类名。 (对于您在 Lunar 注册的每个对象类型,您以字符串形式提供一个名称,Lunar 使用该名称来确保对象的类型正确。)
我会接受这样的事情,我必须检查每个可能的子类:
// Also C++, also doesn't work
S32 Robot::getFiringSolution(lua_State *L)
{
GameItem *target = Lunar<Rock>::check(L, 1);
if(!target)
target = Lunar<Stone>::check(L, 1);
if(!target)
target = Lunar<RockyStone>::check(L, 1);
return returnFloat(L, getFireAngle(target));
}
此解决方案的问题在于,如果堆栈中的项目类型不正确,检查函数会生成错误,并且我相信,从堆栈中删除了感兴趣的对象,因此我只有一次尝试获取
我想我需要从堆栈中获取指向 Rock/Stone/RockyStone 对象的指针,弄清楚它是什么类型,然后在使用它之前将其转换为正确的对象。
Lunar 进行类型检查的关键点是:
// from Lunar.h
// get userdata from Lua stack and return pointer to T object
static T *check(lua_State *L, int narg) {
userdataType *ud =
static_cast<userdataType*>(luaL_checkudata(L, narg, T::className));
if(!ud) luaL_typerror(L, narg, T::className);
return ud->pT; // pointer to T object
}
如果我这样调用它:
GameItem *target = Lunar<Rock>::check(L, 1);
然后 luaL_checkudata() 检查堆栈中的项目是否为 Rock。如果是这样,一切都很好,它返回一个指向我的 Rock 对象的指针,该对象被传递回 getFiringSolution() 方法。如果堆栈上有非 Rock 项目,则转换返回 null,并调用 luaL_typerror(),这会将应用程序发送到 lala land(错误处理打印诊断信息并以极端偏见终止机器人)。
关于如何推进这件事有什么想法吗?
非常感谢!!
我想出的最佳解决方案...丑陋,但有效
根据下面的建议,我想到了这个:
template <class T>
T *checkItem(lua_State *L)
{
luaL_getmetatable(L, T::className);
if(lua_rawequal(L, -1, -2)) // Lua object on stack is of class <T>
{
lua_pop(L, 2); // Remove both metatables
return Lunar<T>::check(L, 1); // Return our object
}
else // Object on stack is something else
{
lua_pop(L, 1); // Remove <T>'s metatable, leave the other in place
// for further comparison
return NULL;
}
}
然后,以后……
S32 Robot::getFiringSolution(lua_State *L)
{
GameItem *target;
lua_getmetatable(L, 1); // Get metatable for first item on the stack
target = checkItem<Rock>(L);
if(!target)
target = checkItem<Stone>(L);
if(!target)
target = checkItem<RockyStone>(L);
if(!target) // Ultimately failed to figure out what this object is.
{
lua_pop(L, 1); // Clean up
luaL_typerror(L, 1, "GameItem"); // Raise an error
return returnNil(L); // Return nil, but I don't think this
// statement will ever get run
}
return returnFloat(L, getFireAngle(target));
}
我可以用它做进一步的优化......我真的很想弄清楚如何将它折叠成一个循环,因为实际上,我要处理的类要多于三个,并且这个过程有点麻烦。
对上述解决方案略有改进
C++:
GameItem *LuaObject::getItem(lua_State *L, S32 index, U32 type)
{
switch(type)
{
case RockType:
return Lunar<Rock>::check(L, index);
case StoneType:
return Lunar<Stone>::check(L, index);
case RockyStoneType:
return Lunar<RockyStone>::check(L, index);
default:
displayError();
}
}
然后,以后……
S32 Robot::getFiringSolution(lua_State *L)
{
S32 type = getInteger(L, 1); // My fn to pop int from stack
GameItem *target = getItem(L, 2, type);
return returnFloat(L, getFireAngle(target)); // My fn to push float to stack
}
Lua 辅助函数,包含在一个单独的文件中,以避免用户需要手动将其添加到他们的代码中:
function getFiringSolution( item )
type = item:getClassID() -- Returns an integer id unique to each class
if( type == nil ) then
return nil
end
return bot:getFiringSolution( type, item )
end
用户从 Lua 中这样调用:
angle = getFiringSolution( item )
最佳答案
我认为您试图在错误的地方执行方法分派(dispatch)。 (这个问题是 所有 使 Lua 与 C 或 C++ 交互的“自动化”方式存在困难的征兆:对于它们中的每一个,幕后都有一些魔法在进行,而且并不总是如何让它工作很明显。我不明白为什么更多的人不只使用 Lua 的 C API。)
我查看了 Lunar 网页,在我看来您似乎需要创建一个 methods
类型表 T
然后调用Luna<T>::Register
方法。有一个 simple example on the web .如果我正确阅读了代码,那么您问题中的胶水代码实际上都不是使用 Lunar 做事的推荐方法。 (我还假设您可以完全将这些方法实现为 C++ 调用。)
这一切都非常狡猾,因为有关 Lunar 的文档很薄。一个明智的选择是自己完成所有工作,并将每个 C++ 类型与包含其方法的 Lua 表相关联。然后你有 Lua __index
元方法查询该表,Bob 是你的叔叔。 Lunar 正在做一些与这些接近的事情,但是它充分地使用了 C++ 模板来装饰我不确定如何让它工作的其他 goo。
模板的东西非常聪明。您可能想要花时间深入了解它的工作原理,或者重新考虑是否要使用它以及如何使用它。
总结:对于每个类,制作一个明确的方法表,并使用农历注册每个类Register
方法。或者自己动手。
关于c++ - Lua、C++ 和穷人的子类化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/866362/
如何从 a.lua 传递值至 b.lua ? 让我们说在我的 a.lua我有这个变量代码。 local value = "Hello WOrld!" director:changeScene ("b"
我有一个使用命令行解释器运行的 lua 脚本,该脚本需要从文件加载表。 该表存储如下: create_object_action = { reflexive = true, which
我通过静态链接的方式在我的项目中嵌入了 Win32 上的 Lua(不,我不能切换到 DLL)。我想捆绑更多使用 native 代码的 Lua 扩展 - 而不仅仅是纯 .lua 文件。具体来说,我想捆绑
我需要一些帮助来解析 lua 文件的命令行。我正在执行一个 lua 文件,该 lua 文件有一个命令“dofile(2nd.lua-file)”,但是,我想通过第一个 lua 文件将一些参数传递给第二
这是我的代码示例: listOfPeople = {} listOfPeople["test"] = "hello" listOfPeople = nil “hello”字符串是否丢失并形成内存泄漏?
在一些源代码中,我看到了“Underscore.lua”模块的用法。 _ = require 'underscore' 描述如下: Underscore.lua is a Lua library th
在一些源代码中,我看到了“Underscore.lua”模块的用法。 _ = require 'underscore' 描述如下: Underscore.lua is a Lua library th
我一直在编程 io.write("How many languages do you speak?\n") answer = io.read() if (answer == 1) then io.wr
这个问题在这里已经有了答案: Getting multiple values from a function without creating a variables in LUA (2 个答案)
在阅读 Lua manual 时我遇到了这部分: 函数调用和赋值都可以以左括号开头。这种可能性导致了 Lua 语法中的歧义。考虑以下片段: a = b + c (print or io.write)(
假设我有以下循环: for name in poll() do if name == "quit" then return 0 end end "quit" 字符串是否
Pandoc 通过其 --lua-filter 参数原生支持 lua 过滤器。 但是,我想知道它使用的是什么版本的 lua,以及是否可以将 lua 模块(我相信它依赖于 C 代码)导入其中。 这是我调
这种语言是面向对象的语言吗? 它经常用作OO语言吗? 最佳答案 Lua 完全有能力 prototype-based类似于 JavaScript 的面向对象编程。 Prototype-based pro
我想从 C++ 传递一个 Lua 脚本(Lua 解释器可以处理的代码)并取回结果。 我在网上查看,但找不到任何可以帮助我的示例。我可以从 C++ 调用 Lua 函数,但这需要您使用 Lua 函数创建一
我正在阅读“在 Lua 中编程”,但我不明白这段代码中 Lua 中函数的行为: function newCounter () local i = 0 return function () --
我最近一直在查找 Lua 中的链表,并有一个简单的问题,到目前为止我还没有找到答案 local head = nil head = {next = head, value = "d"} head =
我知道有tonumber()函数,但是问题是我需要转换较大的数字,例如1000100110100011111010101001001001001100100101。我可以自己写,但是有没有办法将其集成
是否可以在 Lua 中对多个值执行算术运算。 我在 Windows 5.1.4 上使用 Lua。 目前我必须将多个值放入一个表中,然后解压缩它们,我希望能够跳过这一步。 是否可以。 这是我目前拥有的:
有什么区别吗 local splitPathFileExtension = function (res) end 和 function splitPathFileExtension(res) end
在下面的代码中,谁能解释一下 b,a = a,b 内部是如何工作的? -- Variable definition: local a, b -- Initialization a = 10 b = 3
我是一名优秀的程序员,十分优秀!