当前位置: 首页 > news >正文

lua android异常捕获,使用lua实现try-catch异常捕获

lua原生并没有提供try-catch的语法来捕获异常处理,但是提供了pcall/xpcall等接口,可在保护模式下执行lua函数。

因此,可以通过封装这两个接口,来实现try-catch块的捕获机制。

我们可以先来看下,封装后的try-catch使用方式:

try

{

-- try 代码块

function ()

error("error message")

end,

-- catch 代码块

catch

{

-- 发生异常后,被执行

function (errors)

print(errors)

end

}

}

上面的代码中,在try块内部认为引发了一个异常,并且抛出错误消息,在catch中进行了捕获,并且将错误消息进行输出显示。

这里除了对pcall/xpcall进行了封装,用来捕获异常信息,还利用了lua的函数调用语法特性,在只有一个参数传递的情况下,lua可以直接传递一个table类型,并且省略()

其实try后面的整个{...} 都是一个table而已,作为参数传递给了try函数,其具体实现如下:

function try(block)

-- get the try function

local try = block[1]

assert(try)

-- get catch and finally functions

local funcs = block[2]

if funcs and block[3] then

table.join2(funcs, block[2])

end

-- try to call it

local ok, errors = pcall(try)

if not ok then

-- run the catch function

if funcs and funcs.catch then

funcs.catch(errors)

end

end

-- run the finally function

if funcs and funcs.finally then

funcs.finally(ok, errors)

end

-- ok?

if ok then

return errors

end

end

可以看到这里用了pcall来实际调用try块里面的函数,这样就算函数内部出现异常,也不会中断程序,pcall会返回false表示运行失败

并且返回实际的出错信息,如果想要自定义格式化错误信息,可以通过调用xpcall来替换pcall,这个接口与pcall相比,多了个错误处理函数:

local ok, errors = xpcall(try, debug.traceback)

你可以直接传入debug.traceback,使用默认的traceback处理接口,也可以自定义一个处理函数:

-- traceback

function my_traceback(errors)

-- make results

local level = 2

while true do

-- get debug info

local info = debug.getinfo(level, "Sln")

-- end?

if not info or (info.name and info.name == "xpcall") then

break

end

-- function?

if info.what == "C" then

results = results .. string.format(" [C]: in function '%s'\n", info.name)

elseif info.name then

results = results .. string.format(" [%s:%d]: in function '%s'\n", info.short_src, info.currentline, info.name)

elseif info.what == "main" then

results = results .. string.format(" [%s:%d]: in main chunk\n", info.short_src, info.currentline)

break

else

results = results .. string.format(" [%s:%d]:\n", info.short_src, info.currentline)

end

-- next

level = level + 1

end

-- ok?

return results

end

-- 调用自定义traceback函数

local ok, errors = xpcall(try, my_traceback)

回到try-catch上来,通过上面的实现,会发现里面其实还有个finally的处理,这个的作用是对于try{}代码块,不管是否执行成功,都会执行到finally块中

也就说,其实上面的实现,完整的支持语法是:try-catch-finally模式,其中catch和finally都是可选的,根据自己的实际需求提供

例如:

try

{

-- try 代码块

function ()

error("error message")

end,

-- catch 代码块

catch

{

-- 发生异常后,被执行

function (errors)

print(errors)

end

},

-- finally 代码块

finally

{

-- 最后都会执行到这里

function (ok, errors)

-- 如果try{}中存在异常,ok为true,errors为错误信息,否则为false,errors为try中的返回值

end

}

}

或者只有finally块:

try

{

-- try 代码块

function ()

return "info"

end,

-- finally 代码块

finally

{

-- 由于此try代码没发生异常,因此ok为true,errors为返回值: "info"

function (ok, errors)

end

}

}

处理可以在finally中获取try里面的正常返回值,其实在仅有try的情况下,也是可以获取返回值的:

-- 如果没发生异常,result 为返回值:"xxxx",否则为nil

local result = try

{

function ()

return "xxxx"

end

}

可以看到,这个基于pcall的try-catch-finally异常捕获封装,使用上还是非常灵活的,而且其实现相当的简单

这也充分说明了lua是一门已非常强大灵活,又非常精简的语言。

在xmake的自定义脚本、插件开发中,也是完全基于此异常捕获机制

这样使得扩展脚本的开发非常的精简可读,省去了繁琐的if err ~= nil then返回值判断,在发生错误时,xmake会直接抛出异常进行中断,然后高亮提示详细的错误信息。

例如:

target("test")

set_kind("binary")

add_files("src/*.c")

-- 在编译完ios程序后,对目标程序进行ldid签名

after_build(function (target))

os.run("ldid -S %s", target:targetfile())

end

只需要一行os.run就行了,也不需要返回值判断是否运行成功,因为运行失败后,xmake会自动抛异常,中断程序并且提示错误

如果你想在运行失败后,不直接中断xmake,继续往下运行,可以自己加个try快就行了:

target("test")

set_kind("binary")

add_files("src/*.c")

after_build(function (target))

try

{

function ()

os.run("ldid -S %s", target:targetfile())

end

}

end

如果还想捕获出错信息,可以再加个catch:

target("test")

set_kind("binary")

add_files("src/*.c")

after_build(function (target))

try

{

function ()

os.run("ldid -S %s", target:targetfile())

end,

catch

{

function (errors)

print(errors)

end

}

}

end

不过一般情况下,在xmake中写自定义脚本,是不需要手动加try-catch的,直接调用各种api,出错后让xmake默认的处理程序接管,直接中断就行了。。

最后附上try-catch-finally实现的相关完整源码:

相关文章:

  • 弹出自动消失html,用JS实现弹出div层过2秒自动消失的效果
  • html5主题标记是那个,网页文件主体标记 index.html是什么文件
  • html5走格子游戏,JS/HTML5游戏常用算法之碰撞检测 地图格子算法实例详解
  • html导航栏点击显示该栏内容,点击导航栏,实现下方内容改变
  • html 安卓 web 页面布局,webApp 页面布局
  • 学 HTML5 开发 零基础 经验,零基础能不能学会HTML5开发技术?
  • html表示dom怎么设置,{HTML5}DOM 和 CSS 操作-第二节-设置元素及内容
  • 中职计算机应用基础教案1,中职计算机应用基础教案版.ppt
  • 计算机未来发展趋势多级化,计算机的未来发展趋势
  • 学城市轨道和计算机专业哪个好,2019湖南考生学城市轨道交通通信信号技术专业选什么大学好?...
  • 我查学生学的电子计算机要,计算机网络及应用
  • HTML项目做什么好,node适合做什么项目
  • 微型计算机原理8255a考研题,上海交通大学1999年硕士研究生入学考试试题 微型计算机原理与应用(含数字电路)...
  • html5 background-size,CSS3属性background-size使用指南
  • 对计算机应用的,计算机应用技术对企业信息化作用
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • es6--symbol
  • Javascript编码规范
  • JS学习笔记——闭包
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • PHP变量
  • Protobuf3语言指南
  • SpiderData 2019年2月23日 DApp数据排行榜
  • SQL 难点解决:记录的引用
  • 阿里研究院入选中国企业智库系统影响力榜
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 关于for循环的简单归纳
  • 简单易用的leetcode开发测试工具(npm)
  • 实现简单的正则表达式引擎
  • 数据仓库的几种建模方法
  • #### go map 底层结构 ####
  • #1014 : Trie树
  • $().each和$.each的区别
  • (003)SlickEdit Unity的补全
  • (1)(1.13) SiK无线电高级配置(五)
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (篇九)MySQL常用内置函数
  • (图)IntelliTrace Tools 跟踪云端程序
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET程序员迈向卓越的必由之路
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • .NET下ASPX编程的几个小问题
  • [].slice.call()将类数组转化为真正的数组
  • [1525]字符统计2 (哈希)SDUT
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  • [dfs] 图案计数
  • [echarts] y轴不显示0
  • [ffmpeg] x264 配置参数解析