[tolua++] 永远不要用tolua.type

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

先说一下项目,用CEGUI做界面,然后由tolua++导出各种函数给lua使用。

//基类
namespace CEGUI {
class Window{
...
void setText(const String&text, COLOR c=COLOR_BLACK);
}; // end of Window
//StaticText类
class StaticText:public Window
{
}
//ItemCell类
class ItemCell:public Window
{
...
void setText(const String& text);  //实际上此方法会隐藏基类方法
}
...
} //end namespace CEGUI

// lua代码这样写

local win = WindowManager:getWindow("xxx") 

win:setText("text message", COLOR_RED);


一般来讲getWindow返回类型是"CEGUI::Window",但是我们发现在win:setText这行代码,偶发性会报错,概率比较低:

error in function "setText", argument #3 is number;  "[no object] expected". 

尝试把COLOR_RED参数去掉就不报错了。

把win类型用tolua.type(win)打印出来,发现报错的时候类型不是"CEGUI::Window",而是"CEGUI::ItemCell",这就很奇怪了,为什么类型会变呢?

首先怀疑是CEGUI的bug,尝试把xxx.layout简化,只保留一个StaticText控件,问题依旧存在,基本排除CEGUI出bug的可能性。

查看 tolua++ 依据pkg文件生成的中间文件,发现调用getWindow的地方是这么写:

  CEGUI::Window* tolua_ret = (CEGUI::Window*)  Mtolua_new((CEGUI::Window)());
   tolua_pushusertype(tolua_S,(void*)tolua_ret,"CEGUI::Window");  //这是一个c++方法

查阅tolua++相关资料,tolua_pushusertype主要作用就是构造一个给lua用的userdata对象,大概的逻辑是

将c++对象指针作为key, 类型作为value存储于tolua_ubox表(当然这个表里还有userdata)。若key不存在直接插入即可;若存在则根据继承关系判断是否满足条件,若满足则不做任何处理直接返回此userdata对象,若不满足则修订value类型。

lua伪代码:

function tolua_pushusertype(luaState, pVoid, type)
if  not tolua_ubox[pVoid] then
tolua_ubox[pVoid] = type
.. create userdata and return ...
else
if type_compatible(tolua_ubox[pVoid], type) then
.. find userdata and return ...
end
tolua_ubox[pVoid] = type
.. update userdata and return ...
end
end

下面说下type_compatible逻辑, 如果参数是以下几种情况则返回true,否则返回false

1.ChildClass, BaseClass

2. Type, const Type // tolua++ 认为 Type类型可以当做const Type使用,但不能反过来


好了,解释下最开始遇到的问题,

1.创建了一个 CEGUI::ItemCell对象,返回CEGUI::Window类型,然后转换到 CEGUI::ItemCell类型, 指针地址为p, 然后销毁了, 但是lua并没有立即销毁对应的userdata,而是走自己的gc逻辑

2.创建了一个CEGUI::StaticText对象, 刚好指针也是p,返回userdata对象的时候经过tolua_pushusertype的逻辑处理,类型就变成了 CEGUI::ItemCell类型。

怎么验证这个说法? 

这里有一个例子: http://git.oschina.net/kylescript/bug_of_tolua


怎么修复这个问题呢?

打开文件 tolua_push.c     // tolua++ 1.0.93 或者 1.0.92

注释掉 98-103行

/*  这段代码 与 我们的伪代码type_compatible返回true逻辑是一样的

if (lua_toboolean(L,-1) == 1)   /* if true */
{
lua_pop(L,3); /* mt ubox[u]*/
lua_remove(L, -2);
return;
}

*/

这样就修复掉这个问题了,每次都是修订为参数传的type类型,不再判断继承关系啦。 

但是,这样修改真的没问题吗? 为什么作者要设计这个判断类型关系多次一举呢?

注释掉这5行后新问题出现了。

假如有一个类是这样写的:

class ProblemClass{
public:
...
const ProblemClass & func(...)
{
...
return *this;
}
void change_index(int i) {
_index = i;
}
private:
int  _index;
};

把这个类导入 pkg 文件, 并导出func、change_index方法,我们这样写lua代码

local pc = ProblemClass:new_local()

...

pc:func(...)

pc:change_Index(0) //这行会出错


报错:error in function "change_index", argument #1 is "const Problem";  "Problem" expected". 

什么? 怎么变成const类型了?

原因就是func函数,返回了一个*this,  这个*this地址和pc userdata对应的c++对象地址是一样的,被直接修改掉了!

那问题应该怎么解决或者规避呢?我大概想了两个方案

1. 不修改tolua++,删除ItemCell子类的setText方法,走父类的setText逻辑,或者子类setText干脆换个名字。 (这,这真有点耍流氓的赶脚~~~)

2. 注释掉那5行,,不再判断继承关系。 同时不允许导出类似 const Type& func 函数。


或许,大概,也许,这就是tolua++设计这个继承关系检测的初衷?!怎么看都像是设计缺陷啊~~

Lua调用C++函数:原理、实现与工程实践指南 在软件架构设计中,脚本语言与高性能编译语言的混合编程是一种常见模式,旨在兼顾开发效率与执行性能。其核心原理在于通过特定的应用程序接口(API)和虚拟栈机制,实现两种语言环境间的数据交换与函数调用。这项技术的核心价值在于,它允许开发者将计算密集、底层硬件操作等高性能需求模块用C/C++实现,同时将易变、配置化的业务逻辑交由Lua等脚本处理,从而达成架构解耦与灵活部署。典型的应用场景包括游戏开发中的逻辑与引擎分离、嵌入式系统中的应用层脚本化,以及为大型C++程序提供插件扩展能力。本文将以Lua调用C++函数这一 阅读详情

相关推荐

tolua++-1.0.93

tolua++-1.0.93,tolua++是对C++代码暴露给lua的中间语言,学lua的不要错过

windows下使用SCons编译tolua++

第一次写博客,写的不好

xtaieer的专栏 2040

C++与Lua进数据交换的工具函数

1)tolua.type 返回一个 C++ 对象的类型描述字符串 格式: self.studio.layout = cc.CSLoader:createNode(GAMETABLE_CSB); print(tolua.type(self.studio.layout))               -- 输出 cc.Node 2)tolua.cast 强制转换对象类型 格式: tol

游戏小逗比 577

tolua++相关

tolua++ - Reference Manual http://www.codenix.com/~tolua/tolua++.html

buptip的专栏 622

tolua++实现分析

项目正在使用cocos2dx的lua绑定,绑定的方式是tolua++。对大规模使用lua代码信心不是很足,花了一些时间阅读tolua++的代码,希望对绑定实现的了解,有助于项目对lua代码的把控。从阅读结果上来看,起码在内存管理上,帮助还是很大的。 1.tolua++如何将c++对象导入到lua里 tolua++为每一个传入lua的对象建立一个userdata,userdata的值,是

wtyqm的专栏 2万+

tolua++ 1.0.93集成C/C++和Lua代码的工具

tolua是一款工具,大大简化了C/C++和Lua代码的集成。基于干净的头文件(或从真正的头文件提取),tolua自动生成绑定代码供lua访问C/C++的功能。使用Lua API和标记方法设施(tag method facilities),tolua可以映射C/C++的常量,外部变量,函数,类和方法到Lua。 tolua++tolua的一个扩展版本,一款集成C/C++和Lua代码的工具。 项目

无幻 9147

tolua++使用示例

tolua++使用示例 1.近来想研究tolua++,正好忙里抽闲,看些文章,并做了些总结。 一.环境设置 2.下载lua5.1  并安装 3.下载tolua++/Files/API/tolua-1.0.93.tar.bz2.zip  (下载完成后,把.zip去掉) 4.新建工程lua++(生成静态库),将tolua++解压后的tolua++-1.0.93\src\lib目录

boshuzhang的专栏 1426

tolua++初探(一)

用luaplus试验了下,想把简单的C++类映射到lua脚本中不难,但是复杂一点的,比方说类的聚合、继承等,比较麻烦。我试验了两天,用表中表来实现是可以的,但自己弄太麻烦了。说到底,我只是想用一下而已,不是想从头弄一个系统。    用CEGUI时发现它用了tolua++,从网上DOWN了源码(1.0.92),支持Lua5.1。我用VS2005,用源码包里的sln顺利编译出tolua++

安晓辉生涯——聚焦程序员的职业规划与成长 8644

一步步学tolua++

一步步学tolua++

u011694856的博客 406

ToLua使用笔记(中)

继续看例子 目录 13.CustomLoader:自定义加载器Loader的使用 14.Out:out修饰输入参数 15.ProtoBuffer:编码、解码protobuff消息 16.Int64:在lua中使用int64类 17.Inherit:在Lua中扩展C#对象 18.Bundle:用编辑器脚本将lua脚本打包成assetbundle以及加载使用 19.cjson:待看 ...

u012138730的专栏 5688

TypeScriptToLua如何支持循环引用

TypeScriptToLua如何支持循环引用 循环引用 循环引用(Circular Require, Circular dependencies),在lua环境中,指的是这样的情况: 有两个lua文件A和B,文件A中require了B,文件B中require了A,这样在lua解析时会陷入死循环。 很容易想到,在文件require(也就是加载)的时候,应该有三种状态。 未加载 加载中 加载完成 ...

jrl137824675的专栏 1312

tolua

tolua.type返回一个 C++ 对象的类型描述字符串。local node = display.newNode()print(tolua.type(node))-- 输出 CCNode=========================================================================================tolua...

weixin_34163741的博客 260

在linux上编译tolua++-1.0.93

1,首先安装cmake2.8版本和lua5.1版本(cmake的安装直接用sudo apt-get install cmake即可,lua5.1的安装要下载源码,然后make linux,sudo make linux install。注意在安装lua之前要安装两个库:sudo apt-get...

chiloutao9982的博客 304

uniqsmodel toluapp的一个c++版(tolua++toluapp的一个早期分支)

由于tolua的坑实在是太深,int64搞来搞去就是导不出去,好不容易找了个tolua++的版本可以支持STL容器以及自定义模板还要自己封一个类,官方的例子都各种跑不起来,cpp调lua又不能调试,一个无法优化的工具实在让人很不爽,于是本人决定自己写一个。实现MODEL层的抽离。并且与protobuf兼容。直接生成pb文件。   官网: uniqsmodel   如果打不开,复制粘贴: ...

uniqs 的博客 681

Unity - 搬砖日志 - ToLua 如何屏蔽 wrapper 文件不生成对应的成员(方法、字段) - NoToLuaAttribute

方法很简单:只要我们再 VS 搜索:Lua/Generate All 的字符串,然后一路跟过去逻辑,就能找到下面的代码 IsObsolete 的中文意思:是否过期的;是否被抛弃的; 虽然意思不太适合,但是凑合着能达到一样功能效果就好 我个人觉得这些常用功能,ToLua 作者就应该写再 github 仓库首页下说明 NoToLuaAttribute 之类的使用,对用户友好度会高很多 ...

Jave.Lin 的学习笔记 1442

cocos-x lua tolua

1.tolua.cast(对象,类型名) 强制类型转换 layer->node tolua.cast(layer,"cc.Node") 一般在用于 在方法a定义一个精灵 设置tag为2 但在方法b取出来 它却不是精灵,没有精灵的一些属性和方法。 这个时候要 强制转换了,。 2,tolua.type(类型名) 返回一个 C++ 对象的类型描述字符串。 local node = d...

汐客SeaKr的博客 561

Tolua框架学习之一——LuaInterface

          文章参考来源:https://blog.csdn.net/heyuchang666/article/details/50722658            LuaInterface.Lua类是CLR访问Lua解释器的主要接口,一个LuaInterface.Lua类对象就代表了一个Lua解释器(或Lua执行环境),Lua解释器可以同时存在多个,并且它们之间是完全相互独立的。简单...

Tong1993222的博客 3423

在Lua中使用自定义类——tolua++工具使用(下集)

转载请注明,原文地址: http://blog.csdn.net/musicvs/article/details/8166655    正文: 上回说到,把LuaCocos2d.cpp文件拷到我们的lua工程里,然后,编译。   大功告成……啊才怪啊~!     你会发现一大堆的编译错误,超过100个了,木了个头的。怎么回事,我只能认定是这个工具出问题了。 怎么办?没关系~我

尘墨 1063

Tolua++技术文档

Tolua++技术文档 1.简介 Tolua++是一个编程语言文本转换工具,主要用来将C/C++文件转化成lua需要的接口形式。即把大量的函数转成static int XXX(lua_State* tolua_S)形式,以供注册到lua里面。 Tolua++通过pkg文件来导出需要的类型,函数,对象。 Tolua –o test.c tarray.pkg tarray.pkg里面是对应的

绝迹·危言的专栏 1万+
上一篇: glVertexAttribPointer 到底该怎么用?
love2d
博客等级 码龄11年 1粉丝 3原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值