不太推荐爱度综艺简体背夹电池移动电源怎么样,比价选购

cocos2d-x脚本引擎(JavaScript、Lua等等)的大统一(方案概述) - 为程序员服务
cocos2d-x脚本引擎(JavaScript、Lua等等)的大统一(方案概述)
cocos2d-x支持多种脚本引擎的绑定,例如支持lua(通过lua或luajit)、javascript(通过SpiderMonkey脚本引擎),分别对应libluacocos2d和libjscocos2d两个工程,每个工程里分别对应大量的自动绑定和手动绑定代码。如果需要增加一些引擎功能需要绑定到脚本的话,两个工程都需要修改代码,非常不便于维护。假如希望使用其他脚本引擎的话(例如google红红火火的V8,或者ms的chakra),那得多开几个工程,每个工程都需要实现几乎一样,但是又不一样的代码。现在我提出一种思想,来解决这类问题。
现有的脚本引擎多如牛毛,而不同企业间可能有不同的技术积累,希望选择不一样的脚本引擎,有的python蟒蛇派,有的是lua派,有的是ruby派,还有JavaScript、lua等等等等,所以,JavaScript和Lua不应该成为二选一。
而这些脚本引擎之间,有很多的共同点,例如都是弱类型语言,都是支持那么几种简单类型,都是使用GC机制来回收等等。
脚本引擎统一化,是把多个脚本引擎(lua、JavaScriptCore、chakra、v8、spidermonkey等等)通过同一套抽象接口进行封装,引擎的脚本绑定代码都通过抽象接口来编写。通过选择编译不同的实现层来实现脚本引擎间的切换,而不是每个脚本引擎都要写不一样的脚本绑定代码,这样能大大简化脚本绑定层的维护成本,并能保证所有脚本引擎的接口的绝对一致性,并让用户轻松选择使用哪个脚本引擎,而不限定于必须使用官方选择的引擎。
脚本引擎抽象层API的定义非常关键,概括起来我认为他必须符合以下要求:
1、抽象层的接口必须在各个脚本引擎之间都可以实现,例如:“创建字符串”这个接口,是任意脚本引擎都能实现。
2、抽象层在绑定脚本的过程中是足够用的,例如:我们需要导出一个C++的类,还需要导出类里的函数,还有特殊的结构体,甚至包含lambda表达式,这些都需要考虑进去抽象层定义的需求里。
3、抽象层还必须足够的薄,薄到运行时根本感觉不到他的存在。需要使用“宏”或者inline函数的方式来给这个抽象层减肥,坚决不使用C++类的方式来加厚他。
4、抽象层在使用的过程中必须足够简单,简单到就好像是一个单独的脚本引擎API一样,这些API看上去是大统一的,并且是脚本语言无关的。
在定义抽象层的过程中,我参考了很多别人的方案,最终,我使用 了这么个方案:
1、使用C inline函数来定义API接口函数的声明,各个引擎的实现部分分别实现这些函数
2、定义一些基本类型,基本类型有各个脚本引擎来最终定义,但名字和意义都是统一的,初步定义了这些类型,每个类型在不同脚本引擎中对应的类型分别如下表:
JavaScript
JavaScriptCore
表示脚本中的任意类型
JSValueRef
v8::Local&v8::Value&
JsValueRef
脚本对象,对象可以由key、value组成,可以拥有继承结构
JSObjectRef
v8::Local&v8::Object&
JsValueRef
USFunction
JSObjectRef
v8::Local&v8::Function&
JsValueRef
数组类型,下标从0开始
JSObjectRef
v8::Local&v8::Array&
JsValueRef
键-值配对的map类型
JSObjectRef
v8::Local&v8::Object&
JsValueRef
值作为键也作为值得列表,值不能重复
JSObjectRef
v8::Local&v8::Object&
JsValueRef
JSValueRef
v8::Local&v8::Number&
JsValueRef
JSValueRef
v8::Local&v8::Boolean&
JsValueRef
字符串类型
JSValueRef
v8::Local&v8::String&
JsValueRef
内存块缓存对象
JSValueRef
v8::Local&v8::Int8Array&
JsValueRef
USConstructor
对象实例的构造器,用来导出C++类
JSValueRef
v8::Local&v8::Object&
JsValueRef
3、定义一批API,用以对以上定义的基本类型进行创建、调用、修改等操作,例如创建的过程API定义成这种形式:
// 创建Null值
inline USValue createUSNull();
// 创建Undefined值
inline USValue createUSUndefined();
// 创建普通的对象
inline USObject createUSObject();
// 创建数组
inline USArray createUSArray(int length = 0);
// 创建Map
inline USMap createUSMap();
// 创建Set
inline USSet createUSSet();
// 创建字符串
inline USString createUSString(const char *str, int length = -1);
// 创建Buffer,将会拷贝数据到Buffer中,脚本引擎负责销毁
inline USBuffer createUSBuffer(const char *buffer, size_t size);
// 创建一个脚本函数,函数调用时会回调到callback,并带上data
USFunction createUSFunction(USFunctionCallback callback, void *data = nullptr, const char *name = nullptr);
// 创建数字
inline USNumber createUSNumber(double number);
// 创建bool
inline USBoolean createUSBoolean(bool value);
// 创建对象构造器
USConstructor USClassCreateConstructor(const USClass &cls);
抽象层定义好后,需要经过大量的努力,才能在各个脚本引擎间的最终实现。当最终实现完毕后,就可以下一步工作:
1、把cocos2d-x对于自动绑定代码的template类进行修改,修改成使用统一脚本引擎的API
2、把cocos2d-x对于手动绑定的代码如法炮制
3、使用不同的引擎实现来编译
经过这样如法炮制之后,最终cocos2d-x只剩下一套脚本绑定的工程,而通过选择不同的底层脚本引擎,却可以编译出完全不一样的脚本引擎版本。
经过cocos2d-x github社区的努力,最终应该会出现不同的fork,如python、ruby等等各种语言出现各种绑定版本,而这种绑定版本的出现,只需实现抽象层API的基本API即可。
至此cocos2d-x的脚本引擎统一即可完成大业。
但,事情还没完,我在下一篇中,将会讲到抽象API的详细定义,敬请期待下一篇。
专注于C++技术
原文地址:, 感谢原作者分享。
您可能感兴趣的代码|||||||||||||||||
当前位置:&>>&&&&&正文
苹果发警告邮件 iOS手游热更新全面被禁?
  今天,全球不少开发者纷纷收到了发自苹果的警告邮件,提示开发者的APP因违反苹果审核规则将被appstore拒绝审核通过。
  在事件发生后,github,苹果开发者社区上大量开发者加入了该问题的讨论。有开发者反馈自己的app已在appstore搜索不到、但未下架。不过也有某开发者反应,自己使用了JSPatch的两个APP今天上架了appstore但未受到警告邮件。
  根据开发者讨论的结果,主要问题出在苹果审核规则中禁止下载可执行代码,这变相的意思就是禁止app热更新,而据开发者的猜测,苹果应该是采取了批量扫描runtime并给所有涉嫌违规的app的开发者群发了邮件,虽然不是所有开发者收到了该邮件,但涉及该问题的开发者数量依旧非常庞大。
  一直以来,脚本热更新广泛被中国地区iOS开发者采用,主要原因是苹果app提交审核等待时间过长,并不利于游戏、APP快速更新迭代,假若此次热更新被苹果全面禁止,这将极大的影响中国地区iOS开发者。
  苹果开发者条款下:
  3.3.2 Except as set forth in the next paragraph, and Application may not download or install executable code. Interpreted code may only be used in an Application if all scripts, code and interpreters are packaged in the Application and not downloaded.
  按照规定:
  在应用/游戏里面使用Lua或JavaScript脚本是OK的,这个没问题。
  但使用脚本进行热更新,这是违反苹果开发者条款的。
  有开发者指出可能还有一个重要原因是苹果要针对微软VS2017:
  昨天晚上微软发布了Visual Studio 2017,自带基于React Native的iOS开发功能,鉴于微软这两年来开源的力度,发布这一功能似乎是在抢占开发者市场。结果就是有了VS2017,在非苹果上开发iOS应用更容易了。所以,苹果在这个节骨眼发出这样的警告邮件,其实暗地里就是要和微软互怼。
  对此次事件,cocos2d-x引擎创始人王哲对gamelook表示:“此前,国内大家这么用热更,其实都是为了提高用户体验,没人乱来,这个苹果利益诉求一致,所以苹果也就睁只眼闭只眼了。而今天的主要问题是APP涉及到动态加载脚本运行,因为苹果不希望你审核通过的是应用A,然后动态热更新以下变成功能完全不同的应用B。初步来看,可能是苹果针对rollout,jspatch这些热更新框架。”
  在该问题的讨论区中,有开发者总结认为,使用了 rollout,react native,weex,JSPatch,bugtags,个推 ,bugly with hotfix库的APP会被苹果审核盯上。
  而解决办法方面,有开发者建议:“如果是类JSPatch这种只用来热更新的,暂时去掉这些热更新的库吧,或者观望阵子再上架新包。如果是类React Native,抓紧转行吧。”
责任编辑:
48小时点击排行
共青团中央主办 共青团中央网络影视中心承办 版权所有:中国青年网iOS 热更新解读(一)APatch & JavaScriptCore - 推酷
iOS 热更新解读(一)APatch & JavaScriptCore
iOS 动态更新的几种方案
WebView 加载 HTML5 动态更新。
React Native/weex js 动态更新。
lua 脚本文件控制动态更新(代表框架
js 脚本文件控制动态更新(代表框架
其中 WaxPatch 和 JSPatch 是使用较广泛的两种热修复方案。而苹果 review guideline 提到只允通过 JavaScriptCore.framework 或 WebKit 执行脚本,因此 JSPatch 是真正被 Apple 官方支持的。此外鉴于 JavaScript 比 lua 语言更亲民,使用系统内置的 JavaScriptCore.framework 而无需内嵌lua脚本引擎来解释运行lua代码,JSPatch 便成为目前 iOS 热修复使用最多,效果也最佳的方案。
有关上述几种热修复方案的比较可阅读这两篇文章:
APatch 与 JSPatch 的关系
JSPatch 使用时需要一个后台下发和管理脚本。阿里百川 HotFix 平台帮助开发者做了这些事。通过提供脚本托管、版本管理、脚本文件及传输过程加密等服务,让开发者无需搭建后台和关心部署操作,只需引入一个 SDK 即可直接使用 JSPatch 进行热修复。这个 SDK 就是 APatch(iOS)。
APatch 在 JSPatch 核心代码的基础上封装了向 HotFix 平台请求脚本/传输解密/脚本管理/本地调试等功能,是配合阿里百川 HotFix 平台一起使用的。
APatch 工作流程
JSPatch 脚本执行权限很高,若被第三方篡改会
。因此 APatch 和 HotFix 平台都对安全问题考虑良多。
从上图可看出,客户端从服务器下载 Patch 之前先要下载指定 Patch 配置信息即 PatchInfo ,其中包含了 Patch 文件密钥 file_token 。 服务端: - 对 file_token 用 RSA 公钥加密。 - 对 PatchInfo 原始数据采用 HMacSha1 算法计算的哈希值,并将原始数据和哈希值 serviceToken 放在同一消息中传送给客户端。
客户端: - 使用 secret 计算所接收数据的哈希值。 - 检查计算所得的 HMAC 是否与传送的 HMAC 匹配。 - 只有 PatchInfo 通过校验匹配后才会去下载 Patch 。
另外,update patch 的接口已迁至 https,进一步保证了数据传输的安全。
本地存储的脚本被篡改的机会小很多,只在越狱机器上有点风险,对此 APatch SDK 对下载的脚本进行了AES对称加密,每次读取时: - 客户端使用 RSA 私钥解密 PatchInfo.file_token 获取 key 和 iv 。 - 使用 key 和 iv 进行 AES 解密。
解密成功后的数据存储在 script 中,然后会调用 JSPatch 运行js脚本的接口:
[JPEngine evaluateScript:script];
至此,APatch 的工作已经完成,接下来具体的热修复工作就交给 JSPatch 了。
JSPatch —— 基于 JavaScriptCore.framework
JSPatch 是一个开源项目(
),只需要在项目里引入极小的引擎文件,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,替换任意 Objective-C 原生方法。目前主要用于下发 JS 脚本替换原生 Objective-C 代码,实时修复线上 bug。 ——JSPatch wiki
“极小的引擎文件”指的就是 JavaScriptCore。OS X Mavericks 和 iOS 7 引入了 JavaScriptCore 库,它把 WebKit 的 JavaScript 引擎用 Objective-C 封装,提供了简单、快速、安全的方式接入世界上最流行的语言: - 在 Objective-C 代码中直接执行 JavaScript 代码段; - 在 JavaScript 语言环境里调用 Objective-C 公开给 JavaScript的 方法; - 内存管理和线程封装。
如果未接触过 JavaScriptCore,在深入学习 JSPatch 之前有必要先了解一下这个js引擎怎么使用。
OC 调用 JS
JSContext 是运行 JavaScript 代码的环境。可以在 JSContext 中创建变量、计算、定义方法等:
JSContext *context = [[JSContext alloc] init];
[context evaluateScript:@&var num = 5 + 5&];
[context evaluateScript:@&var names = ['Grace', 'Ada', 'Margaret']&];
[context evaluateScript:@&var triple = function(value) { return value * 3 }&];
JSValue 包装了每一个可能的 JavaScript 值,任何出自 JSContext 的值都被包裹在一个 JSValue 对象中:
JSValue *tripleNum = [context evaluateScript:@&triple(num)&];
//取出jsvalue中的值
NSLog(@&Tripled: %d&, [tripleNum toInt32]);//30
对 JSContext 和 JSValue 实例使用下标可以访问之前创建的 context 的任何值。 JSContext 需要一个字符串下标, JSValue 使用字符串或整数下标来得到里面的对象和数组:
JSValue *names = context[@&names&];
JSValue *initialName = names[0];
NSLog(@&The first name: %@&, [initialName toString]);//Grace
调用JS方法需要使用 callWithArguments: 传递参数:
JSValue *tripleFunction = context[@&triple&];
JSValue *result = [tripleFunction callWithArguments:@[@5]];
NSLog(@&five tripled:%d&,[result toInt32]);
这里使用 Foundation 类型 NSArray 作为参数来直接调用该函数。JavaScriptCore 可以 很轻松地处理这个桥接。 以上js代码都以字符串形式直接出现在oc代码中,实际中也可以在项目中引入.js文件,执行js文件中的内容。即:
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@&main& ofType:@&js&];
NSString *jsCore = [[NSString alloc] initWithData:[[NSFileManager defaultManager] contentsAtPath:path] encoding:NSUTF8StringEncoding];
[context evaluateScript:jsCore];
从JS访问在OC中定义的对象和方法有两种方式:
方式一: JSContext 注册 NSBlock 对象:
context[@&add&] = ^(NSInteger a, NSInteger b) {
NSLog(@&add result:%@&, @(a + b));
context.exceptionHandler = ^(JSContext *con, JSValue *exception) {
NSLog(@&%@&, exception);
con.exception =
//异常处理...
[context evaluateScript:@&add(2,3)&];//5
方式二:OC对象实现 JSExport 协议:
定义一个 Test 类,遵循 JSExport 协议:
// in Test.h -----------------
//定义一个JSExport子协议,暴露OC方法定义
@protocol TestJSExports &JSExport&
- (void)log:(id)
- (void)addX:(int)x withY:(int)y;
@interface Test : NSObject &TestJSExports&
- (void)callOC;
// in Test.m -----------------
@implementation Test
- (void)callOC {
JSContext *context = [[JSContext alloc] init];
//将实现了上面定义的协议的对象设置给JSContext
context[@&Test&] =
//执行在JSContext中的JS代码,即可以执行传入的对象的JSExport协议中定义的方法
[context evaluateScript:@&Test.log('Hello JavaScript')&];
[context evaluateScript:@&Test.addXWithY(1, 2);&];
- (void)log:(id)value {
NSLog(@&value = %@&, value);
- (void)addX:(int)x withY:(int)y {
NSLog(@&x + y = %d&, x + y);
Test *test = [[Test alloc]init];
[test callOC];
//&value = Hello JavaScript&,&x + y = 3&
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致动态语言 & ios程序 - lua基础 -
动态语言 & ios程序 - lua基础
经常有看到一些游戏可以不通过appstore而修改一些东西,比如增加功能。
这个其实就是通过下载脚本来实现的。常见的脚本就是js和lua吧。
个人对lua比较熟悉。
lua这货还是挺牛的,解释器非常小,速度也非常快,和C语言函数的交互也很容易。
集成lua到xcode工程
1. 到lua官网,下载源代码,http://www.lua.org/download.html
2. 在要集成lua的工程里面,添加一个target,选择静态库。
3. 把lua源代码(.h, .c)拉到新建的静态库里面,编译。
4. 在目标工程里面,link刚编译出来的.a文件。如:
这样环境就算弄好了。
先include几个lua的头文件。
//extern &C&
#include &lua.h&
#include &lualib.h&
#include &lauxlib.h&
//}如果是c++环境,则需要把extern &C&打开。
准备Lua脚本文件
这里,就简单的创建一个资源。实际上这个脚步可以从服务器下载,保存在本地机器。
创建本地资源文件很简单,我这里就直接创建一个空的文件,命名为my.lua。
然后写入脚本:
这个脚本非常的简单,就是定义一个全局变量myname和一个函数lefthandcall。
在函数内部调用一个lhc的函数,返回。
调用lua函数
直接给出代码,看注释:
- (IBAction)testLua:(id)sender {
l = luaL_newstate();
// 新建一个lua状态
luaL_openlibs(l);
// 加载lua库
NSString *scriptpath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@&my.lua&];
// 读取资源文件里面的lua文件路径
NSString* content = [NSString stringWithContentsOfFile:scriptpath encoding:NSUTF8StringEncoding error: nil];
int iError = luaL_loadfile(l, scriptpath.UTF8String);
// 加载lua文件
iError = lua_pcall(l, 0, 0, 0);
// 先执行一下,可以获取lua脚本的一些变量
int iTop = lua_gettop(l);
// 获取栈顶元素的索引,这里应该是0,也就是栈还是空的。
lua_getglobal(l, &myname&);
// 获取lua里面的一个名字为myname的全局变量,这个全局变量的值会压栈
iTop = lua_gettop(l);
// 所以这里应该是1, 栈顶索引时1,也就是只有一个元素。
const char* p = lua_tostring(l, -1);
// 可以获取lua脚本里面的myname变量的值。
printf(&global variable value: %s&, p);
lua_pushcfunction(l, myTest);
// 把一个c语言函数压栈。
iTop = lua_gettop(l);
// 现在应该是2
lua_setglobal(l, &lhc&);
// 把栈顶的myTest函数设置成lua环境里面的全局变量,名字为lhc,lua_setglobal函数有出栈功能。
iTop = lua_gettop(l);
// 这个时候,应该是1,这个元素其实就是myname变量的值,可以再次尝试获取。
p = lua_tostring(l, -1);
lua_pop(l, 1);
// 从栈顶移除一个元素。
iTop = lua_gettop(l);
// 应该是0
lua_getglobal(l, &lefthandcall&);
// 获取lua脚本里面的名字为lefthandcall的函数,压栈。
iTop = lua_gettop(l);
// 应该是1
lua_pushnumber(l, 15);
// 压入参数
lua_pushnumber(l, 20);
// 压入参数
iTop = lua_gettop(l);
// 栈顶索引是3,一个lua脚本的函数,2个参数。
iError = lua_pcall(l, 2, 1, 0 );
// 调用lua函数,会把栈里面的lua函数和两个参数移除,然后把返回值压栈。
iTop = lua_gettop(l);
// 3 - 3 + 1 = 1
printf(&ret: %s&, lua_tostring(l, -1));
// 打印返回值。
lua_pop(l, iTop);
// 清空栈。
iTop = lua_gettop(l);
lua_close(l);
// 关闭lua状态。
上面的代码主要做了这么几个事情:
1. 新建一个lua状态
2. 获取一个lua脚本里的全局变量。
3. 把一个C语言函数myTest压栈,并且设置成lua环境里面的一个全局函数。
4. 获取lua脚本的函数,并且压入相应的参数
5. 调用lua脚本函数。
mytest函数代码如下:
int myTest(lua_State* L)
// 这个函数会被脚本执行。
// 先检测传入的2个参数是否为数值型
if (!lua_isnumber(L, 1)){
return lua_error(L);
if (!lua_isnumber(L, 2)){
return lua_error(L);
double a = lua_tonumber(L, 1);
double b = lua_tonumber(L, 2);
a&b?lua_pushnumber(L, a):lua_pushnumber(L, b);
// 把2个参数里面大的值压栈,也就是返回值。
root.myLabel.hidden = NO;
// 显示一个原来是隐藏的label。
基本上,整个过程就是:
1. iOS的按钮响应函数调用lua脚本函数lefthandcall
2. lua脚本函数lefthandcall调用lhc函数
3. lhc是lua环境里的一个全局函数,由#1设置。lhc的本身代码是C语言。也就是上面的myTest函数。
运行一下,就会得到2个结果:
1. myTest函数的返回值,也就是2个参入参数的大的值
2. myTest里面,把一个label给显示出来了。见下图,点击TestLua按钮上,会显示上面的label “Shown by Lua”
在ios开发里面使用lua还是挺简单的,也很好用。上面的例子,我们显示了一个label,实际上可以做更多其他的事情。
比如,扩展一些简单的功能。
有了lua这种动态执行脚本,可以给我们的程序增加一些灵活性。有些时候,做一些功能的改动还是挺好的,可以省去再次审核,但是有时像appstore可能会因为集成了这类功能,而拒绝审核。但是不管怎么样,这总是给了我们一个比较好的小范围调整程序的方法。
当然,如果改动很大,那最好的办法还是发布一个新的app版本,不然lua会整的非常复杂。
xcode 6, iOS sdk 8, lua 5.3
ViewController.m
Created by Kevin on 15/3/3.
Copyright (c) 2015年 Kevin. All rights reserved.
#import &ViewController.h&
//extern &C&
#include &lua.h&
#include &lualib.h&
#include &lauxlib.h&
lua_State *l;
ViewController*
int myTest(lua_State* L)
// 这个函数会被脚本执行。
// 先检测传入的2个参数是否为数值型
if (!lua_isnumber(L, 1)){
return lua_error(L);
if (!lua_isnumber(L, 2)){
return lua_error(L);
double a = lua_tonumber(L, 1);
double b = lua_tonumber(L, 2);
a&b?lua_pushnumber(L, a):lua_pushnumber(L, b);
// 把2个参数里面大的值压栈,也就是返回值。
root.myLabel.hidden = NO;
// 显示一个原来是隐藏的label。
@interface ViewController ()
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (IBAction)testLua:(id)sender {
l = luaL_newstate();
// 新建一个lua状态
luaL_openlibs(l);
// 加载lua库
NSString *scriptpath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@&my.lua&];
// 读取资源文件里面的lua文件路径
NSString* content = [NSString stringWithContentsOfFile:scriptpath encoding:NSUTF8StringEncoding error: nil];
int iError = luaL_loadfile(l, scriptpath.UTF8String);
// 加载lua文件
iError = lua_pcall(l, 0, 0, 0);
// 先执行一下,可以获取lua脚本的一些变量
int iTop = lua_gettop(l);
// 获取栈顶元素的索引,这里应该是0,也就是栈还是空的。
lua_getglobal(l, &myname&);
// 获取lua里面的一个名字为myname的全局变量,这个全局变量的值会压栈
iTop = lua_gettop(l);
// 所以这里应该是1, 栈顶索引时1,也就是只有一个元素。
const char* p = lua_tostring(l, -1);
// 可以获取lua脚本里面的myname变量的值。
printf(&global variable value: %s&, p);
lua_pushcfunction(l, myTest);
// 把一个c语言函数压栈。
iTop = lua_gettop(l);
// 现在应该是2
lua_setglobal(l, &lhc&);
// 把栈顶的myTest函数设置成lua环境里面的全局变量,名字为lhc,lua_setglobal函数有出栈功能。
iTop = lua_gettop(l);
// 这个时候,应该是1,这个元素其实就是myname变量的值,可以再次尝试获取。
p = lua_tostring(l, -1);
lua_pop(l, 1);
// 从栈顶移除一个元素。
iTop = lua_gettop(l);
// 应该是0
lua_getglobal(l, &lefthandcall&);
// 获取lua脚本里面的名字为lefthandcall的函数,压栈。
iTop = lua_gettop(l);
// 应该是1
lua_pushnumber(l, 15);
// 压入参数
lua_pushnumber(l, 20);
// 压入参数
iTop = lua_gettop(l);
// 栈顶索引是3,一个lua脚本的函数,2个参数。
iError = lua_pcall(l, 2, 1, 0 );
// 调用lua函数,会把栈里面的lua函数和两个参数移除,然后把返回值压栈。
iTop = lua_gettop(l);
// 3 - 3 + 1 = 1
printf(&ret: %s&, lua_tostring(l, -1));
// 打印返回值。
lua_pop(l, iTop);
// 清空栈。
iTop = lua_gettop(l);
lua_close(l);
// 关闭lua状态。
更多相关文章
本文作者Cory House是一名软件开发者,独立顾问,热衷于清洁代码.务实开发和响应式本土UI的设计.在文章里,他列举了以JavaScript和C#为例,来说明编程里命名的重要性以及必要性. 大家都知道,良好的变量名和优秀的功能在所有的编程语言里都是及其重要的,那么什么样的命名足够好.能足够体现出 ...
大多数人都愿意用IDE来写Java和C#代码,因为有代码补全.智能格式化,甚至自动重构.在动态语言的世界,情况则不大一样. 原因之一是缺少类似静态语言使用的那种工具,这是由于为动态语言开发这类工具十分困难.不过好在这些动态语言的程序通常短小而简洁(例如和Java相比). 不过,有时候使用集成开发环境 ...
发于程序员2006年5月,有删节和修改.今天突然想起来,觉得还值得拿出来看看,就贴blog 上了,有一些和tiny讨论获得的较新鲜的观点,欢迎拍砖.让我们倒退到60年代末,那个计算机的上古洪荒年代.这时,微处理器诞生了不到10年,这个年代的计算机开始大量使用集成电路,小型机开始替代古老的大家伙们 ...
[51CTO独家特稿]TIOBE近日发布了2010年5月的编程语言排行榜,上期榜单C语言反超Java,本期C继续以18.186%的份额领跑,Java则位居第二.排名三到五位的依然是C++.PHP.VB,以下是本期编程语言排行榜前十名榜单: 更多榜单回顾,欢迎访问:51CTO编程语言排行榜 2010年 ...
[51CTO独家特稿]TIOBE近日发布了2010年5月的编程语言排行榜,上期榜单C语言反超Java,本期C继续以18.186%的份额领跑,Java则位居第二.排名三到五位的依然是C++.PHP.VB,以下是本期编程语言排行榜前十名榜单: 更多榜单回顾,欢迎访问:51CTO编程语言排行榜 2010年 ...
命令格式:./maketek [option] [project] [action] [modules] Option: -t ,-tee :输出log信息到当前终端 -o , -opt=…… : 编译附加条件,一般 ...
这本书是ITPUB开发版几个版主(newkid.bq_wang.dingjun123.wabjtam123.lastwinner.〇〇.贾书民)的联手之作,应邀写篇书评.
如果有人问我学习Oracle ...
xenserver中的windows vm安装后可以通过xencenter设置从光驱启动,而linux vm则没有这样的选项,可以通过以下命令行解决: xe vm-param-set uuid=546f896a-eb ...
有时使用GetConsoleWindow()找控制台窗口的句柄时,会提示出错信息: 'GetConsoleWindow' was not declared in this scope. 解决的方法有: 要么在文件头写 ...
一.版本亮点(一) 深度终端(二) 深度游戏中心(三) 人脸识别(一) 软件中心:保障系统 ...
友情链接:
管理员邮箱:info@

我要回帖

更多关于 上海 爱度蛋糕 的文章

 

随机推荐