[zz]为 Lua 绑定 C/C++ 对象

转载自: http://blog.codingnow.com/2013/01/binding_c_object_for_lua.html

 

如何绑定 C/C++ 对象到 Lua 里?通常是创建一个 userdata ,存放 C/C++ 对象指针,然后给 userdata 添加元表,用 index 元方法映射 C/C++ 中的对象方法。

也有另一个手段,直接用 lightuserdata 保存 C/C++ 对象指针放到 Lua 中,在 Lua 中创建一个 table 附加元表来来包装这个指针,效果是类似的。区别在于对象生命期的管理方式有所不同。就这个问题,几年前我写过一篇 blog 。

绑定 C/C++ 对象到 Lua 里的设计难点往往在这个正确的生命期管理上。因为 C/C++ 没有 GC 系统,依赖手工管理资源;而 Lua 则是利用 GC 做自动回收。这两者的差异容易导致在 Lua 中的对象对应的 C/C++ 对象已经销毁而 Lua 层不自知,或 Lua 层中已无对象之引用,而 C/C++ 层中却未能及时回收资源而造成内存泄露。

理清这个问题,首先你要确定,你打算以 Lua 为主干来维护对象的生命期,还是以 C/C++ 层为主干 Lua 部分只是做一些对这些对象的行为控制。

我个人主张围绕 Lua 来开发,C/C++ 只是写一些性能相关的库供 Lua 调用,即框架层在 Lua 中。这样,C/C++ 层只提供对象的创建和销毁函数,不要用 C 指针做对象的相互引用。Lua 中对象被回收时,销毁对应的 C 对象即可。

但是,也有相当多的项目做不到这点。Lua 是在后期引入的,之前 C/C++ 框架层中已做好了相当之复杂的对象管理。或者构架师不希望把脚本层过多的侵入引擎的设计。

那么,下面给出另一个方案。

我们将包装进 Lua 的 C 对象称为 script object ,那么只需要提供三个函数即可。

int
script_pushobject(lua_State *L, void * object) {void **ud;if (luaL_newmetatable(L, "script")) {// 在注册表中创建一个表存放所有的 object 指针到 userdata 的关系。// 这个表应该是一个 weak table ,当 Lua 中不再存在对 C 对象的引用会删除对应的记录。lua_newtable(L);lua_pushliteral(L, "kv");lua_setfield(L, -2, "__mode");lua_setmetatable(L, -2);}lua_rawgetp(L,-1,object);if (lua_type(L,-1)==LUA_TUSERDATA) {ud = (void **)lua_touserdata(L,-1);if (*ud == object) {lua_replace(L, -2);return 0;}// C 对象指针被释放后,有可能地址被重用。// 这个时候,可能取到曾经保存起来的 userdata ,里面的指针必然为空。assert(*ud == NULL);}ud = (void **)lua_newuserdata(L, sizeof(void*));*ud = object;lua_pushvalue(L, -1);lua_rawsetp(L, -4, object);lua_replace(L, -3);lua_pop(L,1);return 1;
}

这个函数把一个 C 对象指针置入对应的 userdata ,如果是第一次 push 则创建出新的 userdata ,否则复用曾经创建过的。

void *
script_toobject(lua_State *L, int index) {void **ud = (void **)lua_touserdata(L,index);if (ud == NULL)return NULL;// 如果 object 已在 C 代码中销毁,*ud 为 NULL 。return *ud;
}

这个函数把 index 处的 userdata 转换为一个 C 对象。如果对象已经销毁,则返回 NULL 指针。 在给这个对象绑定 C 方法时,应注意在 toobject 调用后,全部对指针做检查,空指针应该被正确处理。

void
script_deleteobject(lua_State *L, void *object) {luaL_getmetatable(L, "script");if (lua_istable(L,-1)) {lua_rawgetp(L, -1, object);if (lua_type(L,-1) == LUA_TUSERDATA) {void **ud = (void **)lua_touserdata(L,-1);// 这个 assert 防止 deleteobject 被重复调用。assert(*ud == object);// 销毁一个被 Lua 引用住的对象,只需要把 *ud 置为 NULL 。*ud = NULL;}lua_pop(L,2);} else {// 有可能从未调用过 pushobject ,此时注册表中 script 项尚未建立。lua_pop(L,1);}
}

这个函数会解除 C 对象在 Lua 中的引用,后续在 Lua 中对这个对象的访问,都将得到 NULL 指针。


这些代码是在我写这篇 blog 的同时随手写的,并未经过严格测试。它们也有许多改进空间,比如给 C 对象加入类型,对 userdata 做更严格的检查,等等。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文本字符集转换

http://lqqnotes.blog.51cto.com/3329069/659886 拉取数据 在我opensuse下OK 产品的WIN下面乱码 # enca -L 现在文件的语言 -x 需要转换编码 需要转换编码的文件 查看文件编码jinlinux-gzy1:~> enca -d Downloads/store_sdb_ectools_regions_0211-3.csvDownloads/store_sdb…

php 身份认证服务,PHP的HTTP身份认证

PHP 的 HTTP 认证机制仅在 PHP 以 Apache 模块方式运行时才有效,因此该功能不适用于 CGI 版本。在 Apache 模块的 PHP 脚本中,可以用 header() 函数来向客户端浏览器发送“Authentication Required”信息,使其弹出一个用户名/密码输入窗口。当…

C# WPF MVVM开发框架Caliburn.Micro View / View Model 命名⑨

01—约定在收到Caliburn Micro中有关视图和ViewModel解析的反馈后,我们添加了新功能,以简化类型解析,同时保持驱动它的健壮的基于正则表达式的名称转换机制。为了更好地了解这些新功能以及类型解析通常如何在框架中工作,现在是详细…

rman归档删除

rman&#xff1a; delete [all] input 数据库oracle 11g 全备脚本如下&#xff1a;rman target / <<EOFrun {allocate channel t1 type disk; allocate channel t2 type disk; allocate channel t3 type disk; set limit channel t1 kbytes 4194304;set limit channel t…

史上最气人的数学家:文理双全智商还高,说话只说半句,解题只解半个,调戏人调戏了三百年还不够......

全世界只有3.14 % 的人关注了爆炸吧知识大家上学的时候有没有想过&#xff1a;在数学试卷上调戏阅卷人。想想小天&#xff0c;会都不会写&#xff0c;还调戏阅卷人&#xff1f;想都不敢想。但一个知乎大佬就做了。他居然用费马的原话作答&#xff1a;我已经想到了一个极佳的证明…

php验证手机验证码过期,验证过期时间

~~~//说明目前短信验证码发送成功 需要记录具体的验证码到session。//需要保证验证码有过期时间。关于过期时间 可以记录当前发送验证码的时间以及具体的有效时间$dataarray(code>$code,time>time(),//指定当前的时间limit>3600,//表示具体的过期时间);session(telcod…

数据库(连接)

连接&#xff1a; 为什么需要连接&#xff1f;&#xff1a;因为我们需要的数据在不同的表中 内连接&#xff1a; select 列A from 表A inner join 表B on 条件1条件2 在内连接中可以省去 inner 注&#xff1a;on 必须和join 一起出现 他没有单独存在的意义 外连接&#xff1a…

Hello Blazor:(15)使用bUnit进行单元测试

bUnit介绍bUnit是Blazor组件测试库。其目标是使编写全面、稳定的单位测试变得容易。有了bUnit&#xff0c;你可以&#xff1a;使用C#或Razor语法设置和定义测试下的组件使用语义HTML比较器验证结果与组件以及触发事件处理程序进行交互和检查传递参数、级联值并将服务注入测试组…

*p++,(*p)++,*++p,++*p有什么不同

例如int a[5]{1,2,3,4,5}; int *p a;*p 先取指针p指向的值&#xff08;数组第一个元素1&#xff09;&#xff0c;再将指针p自增1&#xff1b;cout << *p; // 结果为 1cout <<(*p); // 1(*p) 先去指针p指向的值&#xff08;数组第一个元素1&#xff09;&#xff…

掌握这个姿势,女友不再叨叨叨

1 请收下我的膝盖2 正确姿势3 前世五百次的回眸 才换来今生的一次神同步4 论引体向上&#xff0c;你是不如我的5 教科书式的傲娇6 只有我最摇摆7 这是什么原理&#xff1f;你点的每个赞&#xff0c;我都认真当成了喜欢

ubuntu安装matlab2009,Ubuntu中安装Matlab2010a

Ubuntu中安装Matlab2010a一&#xff0e;前言&#xff1a;相信大家对于Matlab应该很熟悉吧&#xff0c;我就不多做介绍了。对于如何在Ubuntu中安装Matlab很多人都不懂&#xff0c;大家都是新手&#xff0c;可以理解。我自己本身就是一个菜鸟&#xff0c;所以决定写这篇文章&…

数据结构笔记--栈的总结及java数组实现简单栈结构

杂谈"栈"结构:   栈(Stack)是一种插入删除操作都只能在一个位置上进表,这个位置位于表的末端,叫做栈顶(Top). 对栈的基本操作有push和pop,表示进栈和出栈.也就相当于插入和删除操作. 栈结构又叫做LIFO(后进先出)表.归根结底是一个表结构,因此任何能够实现表结构的方…

45岁,一个平凡大叔的异地打工生活

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#xff0c;首发于 【掘金】&#x1f4e2;作者格言&#xff1a;生活在于…

C之结构体

 C语言中数组允许定义类型的变量,可容纳相同类型的多个数据项,但结构体在C语言编程中,它允许定义不同种类的数据项可供其他用户定义的数据类型。 结构是用来代表一个记录,假设要跟踪图书馆的书籍。可能要跟踪有关每本书以下属性: Title - 标题 Author - 作者 Subject…

用高等数学“铲雪”!这个200多年前的证明太厉害了,有城市用它省了2000多万..........

全世界只有3.14 % 的人关注了爆炸吧知识用高等数学清扫脚下路前几天&#xff0c;北京下了2021年的第一场雪。这让生活在广州的超模君羡慕不已&#xff0c;原本打算春节前去哈尔滨看个冰雕&#xff0c;结果由于各种原因一直都没成行。一个月前被关进小黑屋的设计师妹子刚好来自哈…

matlab排版形式是什么样子,工作型PPT,图文排版的4种常见样式

原标题&#xff1a;工作型PPT&#xff0c;图文排版的4种常见样式图片是PPT中最好用的一种元素&#xff0c;正所谓“一图抵过千言”。但要想让图片真正地发挥价值&#xff0c;图文排版的好坏非常关键。本期将聊聊4种图文排版的处理方法。这些方法也是我们日常工作中的PPT图文排版…

申请格式

格式与范文分析&#xff1a;  &#xff08;1&#xff09;标题  有两种写法&#xff0c;一是直接写“申请书”&#xff0c;另一是在“申请书”前加上内容&#xff0c;如“入党申请书”、“调换工作申请书”等&#xff0c;一般采用第二种。 申请书 &#xff08;2&#xff09;…

基于事件驱动架构构建微服务第15部分:SPA前端

原文链接 https://logcorner.com/building-micro-services-through-event-driven-architecture-part15-spa-front-end/在本教程中&#xff0c;我将展示如何使用angular构建SPA前端来发送命令和请求查询。SPA前端使用commandAPI发送命令&#xff08;创建、更新或删除语音&#x…

BBC又一神作,豆瓣9.8分,美轮美奂的大自然不仅仅属于人类

总有那么一些人&#xff0c;满怀着对世界的好奇&#xff0c;不远万里不畏艰难去穿越世界上每一个角落&#xff0c;为我们呈现出仅凭我们自己绝无可能看到的世间真实与美好。今天给大家推荐一部BBC出品的一部纪录片&#xff0c;纪录片爱好者肯定听过&#xff1a;BBC出品&#xf…