通过栈恢复脚本函数间参数传递

最近处理了一个客户端同事的需求,大体上是这样的: 在一个脚本里调用另一个窗口的 方法 button_down 一类的, 但如果所调用窗口没有被初始化过则需要先绕到c里面去初始化这个窗口,并且通过窗口对象加载其相应的脚本( 即包含 button_down 定义 的脚本) ,然后再调用 此脚本函数。 换一种描述 就是 当函数不存在时自动加载此函数。

第一反应是通过脚本做一个调用壳,在壳里实现判断 函数是不是 nil ,然后对应加载处理。 实现上简单,但面临2个问题,第一个是 按需求来讲,光加载函数并不能达到期望,因为窗口还没初始化, 第二个是 传递给 窗口函数的参数类型和个数不确定,怎么在壳里在加载这个函数的同时能原封不动的传递一下上层的参数,实现一个 类似C++里为传递变参容器va_list的功能 。

在处理第一个问题上,虽然可以额外提供给脚本一个 初始化窗口的接口, 但这样一来窗口和脚本 谁更早存在的 逻辑顺序就得对 脚本 透明,否则会面临初始化一个窗口时其依赖的父窗口还未初始化这种可能,不是一个太安全的方法。 所以这块壳操作还是得交个C里面的封装去做,在uiengine里面维护一份树形信息,保存各个窗口的关系及其对应脚本,方便在加入的时候能只针对本次调用加载所需的未加入脚本,达到最小加载的目的

处理第二个问题就没这么容易了,因为脚本里面 缺乏能传递变参的机制 (或是说目前我还没找到合适的),即便在加载完了所需脚本以后,之前传递的参数已经被壳给拦下来了想要再传递一次就只有调用窗口函数的上层才知道类型和个数了。按处理第一个问题时确定的方式,这层壳是在C里实现的,其实窗口函数所需的参数已经压入栈里了,能不能由壳函数在栈上只提取出窗口函数名这几个参数,而把剩下的参数利用栈再次返回给lua呢(即 lua 通过栈 传给 c的参数 c用完头几个所需的 剩下的参数 仍旧按原来的顺序 再次让lua函数调用) 经过测试证明 这种方式是可行的:

void shell_call(char* funcname)
{
	lua_remove(L,1);

	int count = lua_gettop(L);

	lua_pushstring(L,funcname);
	lua_gettable(L,LUA_GLOBALSINDEX);

	while(false == lua_isfunction(L,-1))
	{
		string _filename = findfuncfile(funcname);
		lua_tinker::dofile(L,_filename.c_str());
		lua_remove(L,-1);
		lua_pushstring(L,funcname);
		lua_gettable(L,LUA_GLOBALSINDEX);
	}

	lua_insert(L,1);

	if (lua_pcall(L,count,0,0) != 0)
	{
		lua_pop(L,1);
	}
}
其中L 为你脚本所在的 Lua_state

第一个lua_remove是从栈底上去掉函数名字 ,接着用lua_gettop 算出传递给窗口函数的参数个数,然后把名字重新压入栈顶,从全局域下取得对应的函数

while 循环的作用是从 findfuncfile里面对 未找到的 funcname的加载其对应的的脚本, 理论上可以用if 替换while,但 由于 findfuncfile也可能是一个和用户交互的过程而用户可能输入错误脚本所以用while循环实现比较好

接下来的 lua_insert 是 把找到的lua functor 对象 从栈顶交换到栈底, 因为接下来的 lua_pcall要求 栈上的顺序是 functor + 参数1 + 参数2 +... 的排列顺序

lua_pcall 里面的 count 是刚刚取得的参数个数, 调用函数成功以后 lua_pop(L,1)将栈清空


通过lua_tinker::def(L,"shell_call",shell_call) 将这个壳注入脚本环境, 就可以通过 shell("button_down ",1,posx,posy) 这种调用到未加载的脚本函数了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值