我目前正在嵌入Lua并将其用作美化的智能配置文件。但是,我觉得我错过了一些东西,因为人们对Lua的使用赞不绝口。
例如,我可以通过显示这个例子轻松解释为什么你可以使用shell脚本而不是C(诚然,boost regexp是过度杀伤):
#include <dirent.h>
#include <stdio.h>
#include <boost/regex.hpp>
int main(int argc, char * argv[]) {
DIR *d;
struct dirent *dir;
boost::regex re(".*\\.cpp$");
if (argc==2) d = opendir(argv[1]); else d = opendir(".");
if (d) {
while ((dir = readdir(d)) != NULL) {
if (boost::regex_match(dir->d_name, re)) printf("%s\n", dir->d_name);
}
closedir(d);
}
return(0);
并将其与:
进行比较for foo in *.cpp; do echo $foo; done;
你能在Lua中给出任何可以让我“点击”的例子吗?
编辑:也许我的问题是我不太了解Lua,因为我发现编写C代码更容易使用它。
EDIT2:
一个例子是C ++和Lua中的玩具阶乘程序:
#include <iostream>
int fact (int n){
if (n==0) return 1; else
return (n*fact(n-1));
}
int main (){
int input;
using namespace std;
cout << "Enter a number: " ;
cin >> input;
cout << "factorial: " << fact(input) << endl;
return 0;
}
的Lua:
function fact (n)
if n==0 then
return 1
else
return n * (fact(n-1))
end
end
print ("enter a number")
a = io.read("*number")
print ("Factorial: ",fact(a))
在这里,程序看起来很相似,但是你可以摆脱的include,namespace和main()声明中显然有些瑕疵。同时删除变量声明和强类型。
现在有人说这是一个优势,它会增加一个更大的计划,还是更多呢?这与bash示例的方式不同。
答案 0 :(得分:10)
使用Lua等脚本语言还有许多其他好处。
Lua与C ++的一些优点:
答案 1 :(得分:4)
脚本语言减少了构建复杂GUI所需的工作量,否则需要大量的框架粘合和重复代码。 Lua绑定提供了几个GUI工具包,包括wxWidgets和IUP toolkit。
在这两种绑定中,第一类函数值和完全闭包使事件回调易于编码和易于使用。
以Lua为核心的大型应用程序(例如Adobe Photoshop Lightroom)有一个外部C / C ++程序,它承载Lua解释器,并通过向该解释器注册C函数来提供对其核心功能的访问。它通常在C函数中实现计算密集型核心功能,但将整个流程,操作甚至GUI布局留给Lua脚本。
我在自己的项目中发现,当与运行时加载的IUP结合使用时,通常情况下,库存独立Lua解释器(lua.exe或wlua.exe)足以用于外部应用程序基于DLL的自定义Lua模块,用C语言编写,实现需要该级别性能的功能,或通过其他C可调用库实现的功能。
我的项目的重点包括:
我最喜欢的一个例子是我为嵌入式系统构建的测试夹具,需要大约1000行Lua和1000行C,在lua.exe下运行,并使用IUP呈现完整的Windows GUI。第一个版本在大约一天内运行。在使用MFC的C ++中,它至少需要一周的工作,以及数千行代码。
答案 2 :(得分:3)
尝试用C / C ++实现一个Lua表,你会看到Lua的强大。
在Lua:
a["index"] = "value"
在C中,首先阅读有关链表......
C ++ STL可能会有所帮助,但它会比Lua更加冗长。
,Lua很有吸引力。与C接口非常容易(恕我直言)。
答案 3 :(得分:3)
我不知道我是否为你点击'但是我会尝试。
嵌入Lua的一个优点是,你不仅可以将它用作配置文件,而且实际上可以通过Lua脚本语言提供你的C / C ++ - 接口到lua和'script'它们的用法。
如果要更改应用程序的行为/逻辑,只需更改Lua脚本中的代码,而无需重新编译整个应用程序。
突出的用途是游戏逻辑,如AI oder状态机,从变化到游戏的快速往返时间对于开发游戏至关重要。
当然,主逻辑必须存在于Lua脚本中,而不是在C / C ++代码中,才能有效地使用。
答案 4 :(得分:2)
使用C编程可能是一项非常繁琐且冗余的任务,与更抽象的高级语言相比,这当然适用。
从这个意义上说,你可以比直接在C中完成任务更快地开始和完成事情,这是因为需要在C语言中明确地和手动地设置,完成和清理的许多事情通常都是隐含的。由Lua等脚本语言自动处理(例如想象内存管理)。
同样,许多更抽象的数据结构和算法通常由这种高级语言直接提供,因此如果您只需要一个标准容器,就不必重新发明轮子并重新实现它(想想链表,树,地图等)。
因此,当使用相当抽象的脚本语言(如Lua甚至Python)时,您可以获得相当好的ROI,特别是如果相应的语言带有良好的核心功能库。
因此,脚本编写实际上是理想的想法和项目的原型,因为那时您需要能够专注于您的工作,而不是大多数项目可能相同的所有机械冗余。
完成基本原型后,您可以随时了解如何进一步改进和优化它,可能是在C空间中重新实现基本的关键功能,以提高运行时性能。
答案 5 :(得分:1)
有关Lua更适合的示例,那么c ++会考虑分发脚本。 Mush Client提供Lua作为脚本语言。如上面的链接所示,你可以用Lua做很多事情来扩展程序。与C ++不同,虽然Lua不需要编译并且可以被限制。例如,您可以沙箱Lua,因此无法访问文件系统。这意味着如果你从别人那里得到一个脚本,它就无法破坏你的数据,因为它无法写入磁盘。
答案 6 :(得分:1)
Lua作为编程语言的主要优点(除了嵌入性)是
for
循环很难找到一个简短的例子来说明所有这些。我的~/bin
目录中有191个Lua脚本;这是一个取pstotext
的输出并连接以连字符结尾的行:
local function printf(...) return io.stdout:write(string.format(...)) end
local function eprintf(...) return io.stderr:write(string.format(...)) end
local strfind, strlen = string.find, string.len
function joined_lines(f)
return coroutine.wrap(function()
local s = ''
for l in f:lines() do
s = s .. l
local n = strlen(s)
if strfind(s, '[%-\173]$', n-1) then
s = string.sub(s, 1, n-1)
else
coroutine.yield(s)
s = ''
end
end
end)
end
-- printf('hyphen is %q; index is %d\n', '', string.byte(''))
for _, f in ipairs(arg) do
for l in joined_lines(io.popen('pstotext ' .. f, 'r')) do
printf('%s\n', l)
end
end
此示例显示了几个有利的功能,但对表格没有任何意义。
这是来自关键词在上下文索引程序中的简短片段,它从表中获取上下文并在上下文中格式化关键词。这个例子更广泛地使用了嵌套函数,并显示了更多的表和字符串:
local function showpos(word, pos, lw, start)
-- word is the key word in which the search string occurs
-- pos is its position in the document
-- lw is the width of the context around the word
-- start is the position of the search string within the word
local shift = (start or 1) - 1 -- number of cols to shift word to align keys
lw = lw - shift -- 'left width'
local rw = cols - 20 - 3 - lw - string.len(words[pos]) -- right width
local data = assert(map:lookup(pos)[1], "no map info for position")
-- data == source of this word
local function range(lo, hi)
-- return words in the range lo..hi, but only in the current section
if lo < data.lo then lo = data.lo end
if hi > data.hi then hi = data.hi end
local t = { }
for i = lo, hi-1 do table.insert(t, words[i]) end
return table.concat(t, ' ')
end
-- grab words on left and right,
-- then format and print as many as we have room for
local left = range(pos-width, pos)
local right = range(pos+1, pos+1+width)
local fmt = string.format('[%%-18.18s] %%%d.%ds %%s %%-%d.%ds\n',
lw, lw, rw, rw)
printf(fmt, data.title, string.sub(left, -lw), word, right)
end
答案 7 :(得分:1)
我使用一个名为Love2D的游戏引擎,它使用Lua编写游戏。所有的系统调用和繁重工作都是在一个读取Lua脚本的C程序中完成的。
使用C或C ++编写游戏时,您会发现自己正在尝试使用系统的细微之处,而不仅仅是实现您的想法。
Lua允许“干净”的脏样编码。
这是一个用纯lua编写的游戏对象的例子:
local GameObj = {} -- {} is an empty table
GameObj.position = {x=0,y=0}
GameObj.components = {}
function GameObject:update()
for i,v in ipairs(self.components) do -- For each component...
v:update(self) -- call the update method
end
end
要实例化:
myObj = setmetatable({},{__index=GameObj})
-- tables can have a meta table which define certain behaviours
-- __index defines a table that is referred to when the table
-- itself doesn't have the requested index
让我们定义一个组件,键盘控制怎么样? 假设我们有一个为我们输入的对象(将提供C端)
KeyBoardControl = {}
function KeyBoardControl:update(caller)
-- assuming "Input", an object that has a isKeyDown function that returns
-- a boolean
if Input.isKeyDown("left") then
caller.position.x = caller.position.x-1
end
if Input.isKeyDown("right") then
caller.position.x = caller.position.x+1
end
if Input.isKeyDown("up") then
caller.position.y = caller.position.y-1
end
if Input.isKeyDown("down") then
caller.position.y = caller.position.y+1
end
end
--Instantiate a new KeyboardControl and add it to our components
table.insert(myObj.components,setmetatable({},{__index=KeyboardControl})
现在当我们调用myObj:update()时,它会检查输入并移动它
假设我们将使用大量具有KeyboardControl的GameObj,我们可以实例化一个原型KeyObj并像使用继承对象那样使用它:
KeyObj = setmetatable( {}, {__index = GameObj} )
table.insert(KeyObj.components,setmetatable( {}, {__index = KeyboardControl} )
myKeyObjs = {}
for i=1,10 do
myKeyObjs[i] = setmetatable( {}, {__index = KeyObj} )
end
现在我们有了一个可以玩的KeyObj表。 在这里,我们可以看到Lua如何为我们提供一个功能强大,易于扩展,灵活的对象系统,它允许我们根据我们试图解决的问题来构建我们的程序,而不是不得不弯曲问题以适应我们的语言
此外,Lua还有一些很好的其他功能,比如作为一流类型的函数,允许lambda编程,匿名函数以及其他通常让comp-sci老师微笑的东西。
答案 8 :(得分:1)