Lua 在.net 中的是非(研究的人似乎不多)

2024-01-31 12:08
文章标签 lua net 研究 是非 似乎

本文主要是介绍Lua 在.net 中的是非(研究的人似乎不多),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

很久没上博客了,换了工作之后一直忙的不可开交,我也自认个人能力比较有限,但无奈的是很多事情都从技术层面上压迫自己,整那些压根就没接触过或不熟悉的东西,。
  
   不过还是能学到不少东西,关于Lua,应该说我是从新魔界游戏才了解的,当时我以为是金酷自己的发明的一种脚本,真是固陋寡闻呀!不是因为技术考虑上需要,我也懒的去研究,原来这个东西是巴西的一个家伙发明的,原本作为C的扩展,最后到成了游戏里吃香的馍馍,包括WOW(本人并不喜欢)居然可以让玩家自己通过LUA脚本来定制客户端,强捍。
  
   到网上一查,嘿嘿,关于LUA的东西到不少,名气还是很大的,至少很多游戏都首选LUA作为脚本引擎,LUA作为纯ANSI C实现的轻量级的虚拟机,且结构简单,优美,额!我才不管它多优美了,不过现在的确是有求于它,主要是由于客户需要能够按它们要求去抓取网页数据并能形成所期望格式的表,这下可为难我了,我没有研究过蜘蛛,只是了解,但我肯定网上找不到一个适合我的,至少我们的客户不是只有一个有这种需要,这对于维护实在是太麻烦,我倒是可以根据你的要求去取网页,分析网页数据,抓取特定部位存,但客户的抓取需求非常多,而且如果人家网站变了,你的重新修改程序,编译发布,工作量可想而知,重要的是,全国有很多远的客户,那个维护就更是麻烦,人都会被整崩溃,于是LUA进入我得视野,我本想自己实现一个简单的,可以通过配置抓取模板来处理网页数据的抓取(这里页面数据的某些抓取部分肯定需要复杂的提取逻辑,程序里写死肯定不好),但想想,自己写反编译器却最终半徒而废,这个由于工作还是可以硬头皮实现,但这种临时拼凑的东西合适吗,估计你要保证稳定工作都要不短的时间,还得功能够强,埃,郁闷死个人。
  
   于是就到处搜索LUA的.NET应用,不过真是可惜,除了LUA自己的一个PDF编程指南外,基于.NET下的LUA的丰富应用的资料还真是少的可怜,就连我寄希望的博客园里搜索也没有找到几篇文章,搜到就一个LUAINTERFACE,这个东西的确让我们搞.NET的对LUA应用作出了贡献,不过网上说什么有一个多核的BUG,会崩溃,虚拟机,那个家伙实在不够意思,给个修改版本的连接居然下不了,对问题的修改地方也一个字都不提,我想,大不了我要求客户机器是单核CPU的不就玩了,耶! LUAINTERFACE并不是LUA虚拟机本身,它是对LUA的一层接口封装,你的有一个LUA的托管C++编译版本的DLL才行,还得有几个C++的运行期文件COPY在一起才能运行。
  
   这个接口,我倒是没有直接用,跑到CODEPLEX里搜到了一个LUANET,还不错,看看DEMO,还是很激动的,居然可以将.NET的类,方法注册到LUA虚拟机里,来扩展LUA虚拟机的API,这个不正是我想要得吗?一个虚拟机引擎,加一堆我针对网页提取,分析的粒子接口,利用LUA脚本来实现抓取模本配置,这样就可以很灵活的针对网页抓取的任务了,后面连程序都不该了,直接发一个XML的抓取模板就可以应付变化,而且可以随意修改,还有我作的一个简陋的智能表单框架,如果加入LUA引擎,岂不威力大增,
  
   不过我在写脚本IDE(简单的^_^)时,调试脚本居然发现,狗日的对中文字符串参数报脚本语法错误,那个郁闷都不知道从那里说去,毕竟俺分析的可以中文网页呀,这该死的ANSI,就没考虑过中国人的感受,郁闷了2天,GOOGLE,BAIDU都翻偏了,由于LUA.NET应用的不多,这个BUG居然没有人提出来,头脑一热,想,干脆自己把LUA的C代码读懂,改为纯C#实现的,这样多好呀,我连名字都想好了,就叫SHARPLUA^_^,不过时程问题,公司可不允许我有足够的时间来改写一个C#版本的虚拟机,如果能解决这个问题多好呀,没法,只有自己调试LUAINTERFACE了,发现到.NET这层的结构没有办法找错误,毕竟人家报的是脚本语法错误,也就是说这个执行已经进入到LUA虚拟机部分的代码了,那部分是C++的,埃,我C++是个半飘水,不熟悉(还是有些基础,自认为C还是整的不错的),找到LUAINTERFACE的开源下载,里面的LUA511就包含了LUA的C实现代码,工程都整了好久,直接下的需要调整编译器设置才能下,跟踪了N久,确认了数个函数后,终于发现可以的导致对中文处理上的代码,我靠,这个不知道算不算是错误,如果LUA是存C++非托管编译的(这个指LUA5。1。4的原始C开源版本),编译后,居然一点问题都没有,但是到.NET里用/CLR编译程托管版本就报这个错误,无语了。比如
  
   LUA5.1.4 VS2005 C++编译 非托管
  
  运行图如下
  
  一点错误都没有,汗
  
  但是.NET下 里死活报一个什么 没有结束的字符串的脚本语法错误,
  
  如果用print('jakskdjfjaf');非中文的话,就一点问题都没有
  
  不管是调用PRINT这个LUA虚礼机内置API出问题,包括所有你定义的变量的中文字符串,或是函数的参数,都无疑例外的出现脚本错误,
  
   最后跟踪C++的代码到了这里 是LUAXLIB.C 里的如下代码
  
  typedef struct LoadS {
   const char *s;
   size_t size;
  } LoadS;
  
  
  static const char *getS (lua_State *L, void *ud, size_t *size) {
   LoadS *ls = (LoadS *)ud; // 这里的*ud是有LUA经过词法解析后放在的作为字符串表达式的一个内存地址
   (void)L;
   if (ls->size == 0) return NULL; // *size到搞什么的,它是存放子串表达式长度的地址 一个int *指针参数
   *size = ls->size; // 比较看了看这里的代码核5.1.4里一模一样,但就是非托管C++里可以,托管的编译就不行
   ls->size = 0;
   return ls->s;
  }
  
  跟踪这里后,我反复看了看,终于发现问题之所在,比如声明一个 表达式 msg='我爱'; 这个语句,LUA这里这
  
  (LoadS *)ud 得到的结构里,长度居然是 9 ,由于C的CHAR是8位的, 很明显中文占2个字节,实际的字节数应该是11才对,就是这个小问题导致LUA语法解析 根据9长度取表达式,刚好取到 ‘爱’字,后面的 ’;2个字符给搞丢了,弄的是自己语法检查就来个 没有结束的字符串表达式,我想这里的(LoadS *) ud没有正确识别字符串的长度,还是有点鄙视LUA的作者的,写个不安全的代码,它应该用系统的strlen函数来完成,嘿嘿,根据我自己的想法,我修改了这段C代码,
  
  static const char *getS (lua_State *L, void *ud, size_t *size) {
   LoadS *ls = (LoadS *)ud;
   (void)L;
   if (ls->size == 0)
   {
   return NULL;
   }
   else
   {
   ls->size=strlen(ls->s); // 修改的地方
   }
   *size = ls->size;
   ls->size = 0;
   return ls->s;
  }
  NND ,问题终于解决了,终于可以心安的用LUA了,觉得LUA实在是好东西,如果你需要一个脚本引擎嵌入到你的C#应用中,玩LUA吧,的确是个好东西,一个可嵌入的脚本引擎,毕竟是开源且免费的。
  
   这篇随笔做抛石头引玉,LUA的.NET 的应用的确不多,有人想搞SHARPLUA的纯C#版本的虚拟机,我就享受成果吧^_^,最后有知道修改LUAINTERFACE多核CPU上的锁的朋友,可以给我留言(就留修改的地方核代码)

 

http://www.webkey.cn/code/view.asp?id=7323

这篇关于Lua 在.net 中的是非(研究的人似乎不多)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/663713

相关文章

Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)

《Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)》本文主要介绍了Golang分布式锁实现,采用Redis+Lua脚本确保原子性,持可重入和自动续期,用于防止超卖及重复下单,具有一定... 目录1 概念应用场景分布式锁必备特性2 思路分析宕机与过期防止误删keyLua保证原子性可重入锁自动

使用easy connect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题

《使用easyconnect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题》:本文主要介绍使用easyconnect之后,maven无法... 目录使用easGWowCy connect之后,maven无法使用,原来需要配置-DJava.net.pr

在.NET平台使用C#为PDF添加各种类型的表单域的方法

《在.NET平台使用C#为PDF添加各种类型的表单域的方法》在日常办公系统开发中,涉及PDF处理相关的开发时,生成可填写的PDF表单是一种常见需求,与静态PDF不同,带有**表单域的文档支持用户直接在... 目录引言使用 PdfTextBoxField 添加文本输入域使用 PdfComboBoxField

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

redis+lua实现分布式限流的示例

《redis+lua实现分布式限流的示例》本文主要介绍了redis+lua实现分布式限流的示例,可以实现复杂的限流逻辑,如滑动窗口限流,并且避免了多步操作导致的并发问题,具有一定的参考价值,感兴趣的可... 目录为什么使用Redis+Lua实现分布式限流使用ZSET也可以实现限流,为什么选择lua的方式实现

基于.NET编写工具类解决JSON乱码问题

《基于.NET编写工具类解决JSON乱码问题》在开发过程中,我们经常会遇到JSON数据处理的问题,尤其是在数据传输和解析过程中,很容易出现编码错误导致的乱码问题,下面我们就来编写一个.NET工具类来解... 目录问题背景核心原理工具类实现使用示例总结在开发过程中,我们经常会遇到jsON数据处理的问题,尤其是

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int