cocos2d-x内部使用tolua进行lua绑定,但是引擎并没有提供一个通用的接口让我们可以把一个lua函数注册给C++层面的回调事件。
翻看引擎的lua绑定代码,我们可以仿照引擎中的方法来做。
值得吐槽的是,这套流程在开发中几乎是不可避免的,而cocos2d-x竟然不把它作为一个公用接口暴露给开发者,而需要我自己动手,真是无奈。


下面以一个简单的消息分发类为例子,演示如何完成这一工作。

MessageDispatcher.h

class MessageDispather
{
public:
static MessageDispather* sharedDispather(); public:
void invokeLuaCallbackFunction(int msgId, const char* text);
void registerScriptHandler(int nHandler); private:
int mLuaHandlerId;
};

MessageDispatcher.cpp

#include "CCLuaEngine.h"

MessageDispather* sharedDispather()
{
static MessageDispather* instance = NULL;
if(instance == NULL) instance = new MessageDispather();
return instance;
} void MessageDispather::invokeLuaCallbackFunction(int msgId, const char* text)
{
if(mScriptHandler > 0)
{
CCLuaStack* stack = CCLuaEngine::defaultEngine()->getLuaStack();
stack->pushInt(msgId);
stack->pushString(text);
stack->executeFunctionByHandler(mScriptHandler, 2);
stack->clean();
}
} void MessageDispather::registerScriptHandler(int nHandler)
{
mLuaHandlerId = nHandler;
}

说明

#include "CCLuaEngine.h"
这个头文件来自cocos2d-x\scripting\lua\cocos2dx_support
整个文件夹里的内容是cocos2d-x引擎做lua绑定时封装的一些工具类。
你需要在你的项目中添加这个目录的include搜索路径。

void registerScriptHandler(int nHandler)
这个函数需要暴露给lua。
在lua中调用这个函数,参数nHandler的位置传进去一个lua函数,就能够在C++这边得到一个nHandler的整数句柄值。
之后任何时间如果想要在C++中调用刚刚注册的lua回调函数,需要以这个整数值来指代那个函数。

void invokeLuaCallbackFunction(int msgId, const char* text)
在C++用调用此函数,我们期待它会调用到一个在lua中定义的回调函数。
具体这个函数里的实现是什么意思,如果你对lua c api有一定了解的话应该很容易能看懂,我就不再做解释。

用于tolua的pkg文件

class MessageDispather
{
static MessageDispather* sharedDispather();
void registerScriptHandler(LUA_FUNCTION nHandler);
};

在lua中使用MessageDispatcher

local function onMessage(msgId, text)
print(msgId, text)
end
MessageDispatcher:sharedDispatcher():registerScriptHandler(onMessage)

万事大吉。。。。。才怪!

有没有发现我们的pkg文件中有一个类型是LUA_FUNCTION??
对,因为这个参数在lua中应该传入一个函数,而到了C++这边我们拿到的却是一个int。
这并不是tolua的缺省行为,而是cocos2d-x针对这种情况做的一个特殊处理。
翻看cocos2d-x的tolua绑定流程,我们可以发现build.bat中的内容是这样的:
tolua++ -L basic.lua -o "../../scripting/lua/cocos2dx_support/LuaCocos2d.cpp" Cocos2d.pkg
这里basic.lua是一些额外的逻辑,其中处理LUA_FUNCTION类型的逻辑也在里面。

那么我们可以照猫画虎,请创建这样一个lua文件:

_is_functions = _is_functions or {}
_to_functions = _to_functions or {} -- register LUA_FUNCTION, LUA_TABLE, LUA_HANDLE type
_to_functions["LUA_FUNCTION"] = "toluafix_ref_function"
_is_functions["LUA_FUNCTION"] = "toluafix_isfunction"
_to_functions["LUA_TABLE"] = "toluafix_totable"
_is_functions["LUA_TABLE"] = "toluafix_istable" local toWrite = {}
local currentString = ''
local out
local WRITE, OUTPUT = write, output function output(s)
out = _OUTPUT
output = OUTPUT -- restore
output(s)
end function write(a)
if out == _OUTPUT then
currentString = currentString .. a
if string.sub(currentString,-1) == '\n' then
toWrite[#toWrite+1] = currentString
currentString = ''
end
else
WRITE(a)
end
end function post_output_hook(package)
local result = table.concat(toWrite)
local function replace(pattern, replacement)
local k = 0
local nxt, currentString = 1, ''
repeat
local s, e = string.find(result, pattern, nxt, true)
if e then
currentString = currentString .. string.sub(result, nxt, s-1) .. replacement
nxt = e + 1
k = k + 1
end
until not e
result = currentString..string.sub(result, nxt)
if k == 0 then print('Pattern not replaced', pattern) end
end replace([[*((LUA_FUNCTION*)]], [[(]])
replace([[tolua_usertype(tolua_S,"LUA_FUNCTION");]], [[]]) WRITE(result)
end

然后在你执行tolua++的时候把这个文件作为-L参数传进去就可以了。

应该真的万事大吉了。

cocos2d-x 2.2.0 如何在lua中注册回调函数给C++的更多相关文章

  1. cocos2d-x 2.2.0 怎样在lua中注冊回调函数给C++

    cocos2d-x内部使用tolua进行lua绑定.可是引擎并没有提供一个通用的接口让我们能够把一个lua函数注冊给C++层面的回调事件. 翻看引擎的lua绑定代码,我们能够仿照引擎中的方法来做. 值 ...

  2. 【转载】如何在 C#中访问 JavaScript函数?

    如何在 C#中访问 JavaScript函数? 时间:13-10-17 栏目:Unity3D教程 作者:zqcyou 评论:0     如何在 C#中访问 JavaScript函数?答案如下:c#代码 ...

  3. iis如何在dos中注册

    iis如何在dos中注册   2009-09-23 08:13 提问者采纳   cd \cd c:\windows\microsoft.net\framework\v2.0.50727aspnet_r ...

  4. lua中调用C++函数

    lua中调用C++函数 我们产品中提供了很多lua-C API给用户在lua中调用,之前一直没用深究其实现原理,只是根据已有的代码在编码.显然这不是一个好的习惯,没用达到知其所以然的目的. 一.基本原 ...

  5. ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings

    问: ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings 答: Dependency injection is possible in filters as ...

  6. Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween

    在上一篇文章 Unity3D热更新之LuaFramework篇[04]--自定义UI监听方法 中,我对LuaBehaviour脚本进行了扩展,添加了两个新的UI监听方法,也提到最好能单写一个脚本处理此 ...

  7. Xcode中c++&Object-C混编,详细介绍如何在cocos2dx中访问object函数以及Apple Api

    转自:http://www.himigame.com/iphone-cocos2dx/743.html Cocos2dx系列博文的上一篇详细介绍了如何在Xcode中利用jni调用Android的Jav ...

  8. Lua中调用C函数

    Lua利用一个虚拟的堆栈来给C传递值或从C获取值.每当Lua调用C函数,都会获得一个新的堆栈,该堆栈初始包含所有的调用C函数所需要的参数值(Lua传给C函数的调用实参),并且C函数执行完毕后,会把返回 ...

  9. Lua中调用C函数(lua-5.2.3)

    Lua能够调用C函数的能力将极大的提高Lua的可扩展性和可用性. 对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们全然能够通过C函数来实现,之后再通过Lua调用指定的C函数. 对于那些可 ...

随机推荐

  1. linux 下的sublime

    Sublime Text 2 的安装 : 在官方网站下载Linux版本  Or  执行 #  wget http://c758482.r82.cf2.rackcdn.com/Sublime%20Tex ...

  2. HDU-1518 Square(DFS)

    Square Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submi ...

  3. webdriver 操作 Firefox 在关闭浏览器时弹出 “Plugin Container for Firefox已停止工作” 处理办法。

    上来先来一个图: 在使用webdriver操作Firefox浏览器的时候,一路顺畅.可是在最后关闭浏览器后,出现了如上面图示的警告!这个警告很早就出现了,因为也不影响测试结果,也就一直没理. 后来新搭 ...

  4. 批量Linux 网络安装环境建立工具cobbler/kickstart

    批量Linux 网络安装环境建立工具网络安装服务器套件:     Cobbler(Red Hat 2008年发布的项目)    Kickstart(Red Hat08年前项目,相关脚本令人望而却步,现 ...

  5. 1 weekend110的复习 + hadoop中的序列化机制 + 流量求和mr程序开发

    以上是,weekend110的yarn的job提交流程源码分析的复习总结 下面呢,来讲weekend110的hadoop中的序列化机制 1363157985066      13726230503  ...

  6. 佛山Uber优步司机奖励政策(2月1日~2月7日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. HTML5 Canvas 颜色填充学习

    ---恢复内容开始--- 如果我们想要给图形上色,有两个重要的属性可以做到:fillStyle 和 strokeStyle. fillStyle = color strokeStyle = color ...

  8. struts2 表单处理

    在这篇教程里我们将探究如何处理表单提交.本文例子介绍: javabean存储表单数据 在action中重写validate方法进行简单的校验 创建一个struts2表单并和javabean匹配 jav ...

  9. 用CRTP在C++中实现静态函数的多态

    我上一篇博客[C++的静态分发(CRTP)和动态分发(虚函数多态)的比较](http://www.cnblogs.com/fresky/p/3504241.html)介绍了如何用CRTP(Curiou ...

  10. SampleManager(赛默飞)