lua脚本调用cocos2dx项目中自定义的C++类

cocos2dx项目中自定义类提供给lua脚本使用。网上找到的方法,大多是改动LuaCocos2d.h,手写pkg文件,手动敲tolua++命令生成适配文件。我找到一个可以不用动LuaCocos2d.h的方法,并写了一个由*.h生成适配文件的工具。现在与各位分享我的做法,嘿嘿~~

1、问题描述:把自定义类MXBase的create方法暴露给lua脚本使用。

MXBase类源码如下:

MXBase.h

//
//  MXBase.h
//  hello_lua
//
//  Created by xingchong on 6/20/13.
//
//

#ifndef hello_lua_MXBase_h
#define hello_lua_MXBase_h

#include "cocos2d.h"

USING_NS_CC;

class MXBase : public CCNode {
    
    
public:
    
    MXBase();
    
    ~MXBase();
    
    static MXBase* create();
    
    bool init();

};


#endif

MXBase.cpp

//
//  MXBase.cpp
//  hello_lua
//
//  Created by xingchong on 6/20/13.
//
//

#include "MXBase.h"
#include "CCLuaEngine.h"

MXBase::MXBase(){
    CCLog("MXBase() is create.....");
}

MXBase::~MXBase(){
    
}


MXBase* MXBase::create(){
    MXBase *pRet = new MXBase();
    if (pRet && pRet->init()) {
        pRet->autorelease();
        return pRet;
    }else{
        CC_SAFE_DELETE(pRet);
        return NULL;
    }
}


bool MXBase::init(){
    CCLog("MXBase init function ...");
    return true;
}


2、生成适配文件

把MXBase.h写成MXBase.pkg,规则是(这是官方的描述):

Writing .pkg files

    1) enum keeps the same
    2) remove CC_DLL for the class defines, pay attention to multi inherites
    3) remove inline keyword for declaration and implementation
    4) remove public protect and private
    5) remove the decalration of class member variable
    6) keep static keyword
    7) remove memeber functions that declared as private or protected 


MXBase.pkg:

$#include "MXBase.h"
$#include "cocos2d.h"

class MXBase : public CCNode 
{

     
     MXBase();
     
     ~MXBase();
     
     static MXBase* create();
     
     bool init();
 
};


把MXBase.pkg生成适配文件MXBaseLoad.h、MXBaseLoad.cpp,生成命令如下:

mac下   ./tolua++ -H loader/MXBaseLoad.h -o loader/MXBaseLoad.cpp pkg/MXBase.pkg

windows下    tolua++ -H loader/MXBaseLoad.h -o loader/MXBaseLoad.cpp pkg/MXBase.pkg

以上生成适配文件的过程,当然是可以手动完成的,我已把这个操作做成工具,源码在github

 https://github.com/xingchong/HFileToPkg.git

感兴趣的学友,可以取下来,共同研究哈。。。

工程目录结构:


中,hfile文件夹放h文件,运行HPkgLoaderMain后,可生成MXBase.pkg、MXBaseLoad.h、MXBaseLoad.cpp、DefinitionLoader.h等文件。

注:在windows下运行HPkgLoaderMain,会用到tolua++.exe; 在mac下运行HPkgLoaderMain,会用到tolua++。tolua++.exe与tolua++的作用是一样的,只是所属平台不同。


3、在cocos2dx工程中,如何用这些生成的文件,以达到lua脚本可以调用MXBase类方法的效果?

Xcode下,新一个cocos2dx_lua工程,把MXBaseLoad.h、MXBaseLoad.cpp、DefinitionLoader.h加入到工程中。


CCLuaEngine的init方法中调用DefinitionLoader类方法:

bool CCLuaEngine::init(void)
{
    m_state = lua_open();
    luaL_openlibs(m_state);
    tolua_Cocos2d_open(m_state);
    
    DefinitionLoader::definitionLoader(m_state);//add by chong
    
    toluafix_open(m_state);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    addLuaLoader(loader_Android);
#endif
    return true;
}

ok,C++部分就这些。


下面看lua脚本,在cocos2dx_lua工程的hello.lua中调用MXBase类的创建方法。

hello.lua部分代码:

-- for CCLuaEngine traceback
function __G__TRACKBACK__(msg)
    print("----------------------------------------")
    print("LUA ERROR: " .. tostring(msg) .. "\n")
    print(debug.traceback())
    print("----------------------------------------")
end

local function main()
    -- avoid memory leak
    collectgarbage("setpause", 100)
    collectgarbage("setstepmul", 5000)

    local cclog = function(...)
        print(string.format(...))
    end

    require "hello2"
    cclog("result is " .. myadd(3, 5))

    ---------------
    local mxBean = MXBase:create()  --就是这句调用

下面运行cocos2dx_lua项目,控制台打印出如下结果:



正是MBase.cpp中写的CCLog,这表示我们lua调用自定义的C++类方法成功!


4、最后,和大家分享一下在用lua做cocos2d-x项目时遇到的干货,虽然是没什么技术含的干货,但也费了好长时间才弄明白,写出来共分享!微笑

1)暴露有脚本回调函数的C++接口,代码报错

举例:暴露此方法    virtual void registerScriptAction(int nHandler,int eventType);

问题:若直接用tolua++生成中间层代码,会提示“期望number,实际为function”。

原因:中间层无法正确识别函数参数

解决方法:把pkg文件中的int nHandler改为LUA_FUNCTION ,再用tolua++生成,

之后根据cocos2d-2.0-rc2-x-2.0.1\tools\tolua++\build.xml替换相应语句。


2)点击事件回调函数,注册时无法判重

问题:向按钮控件注册两次同样的lua方法,判重代码没起作用。

原因: lua方法在C++中被识别为int ,但同一个方法两次注册, int值会不一样;

解决方法:向一个控件注册事件时,而是先移除所有同类事件再注册,使得控件上的同类事件只有一个。


3)lua无法调用C++类的父类方法

问题: NMButton继承Button继承ButtonImage,在lua中NMButton控件调不到ButtonImage的方法。

猜测: 不支持多重继承?不支持隔代继承?

原因:调用NMButton控件时, ButtonImage还未注册。

解决方法: bool LuaEngine::init(void)中的类必须按继承关系依次写顺序不能乱。


4)lua识别C++多继承问题

问题:class A: public B, public C,在lua中,A的对象调不到C类的方法。

原因:lua不能直接找到多继承的父类方法

解决方法:需要显式指定父类,如local a = A:create()a.__C__:methodInC()


5)对象类型丢失,lua只能调到父方法

问题:local button1= panel:searchComponentByID(“button1")Button1只能调到BaseComponent的方法,

调不到Button自己的方法。

原因:通过searchComponentByID得到的对象,有时会出现丢失类型的问题

解决方法:用tolua_cast强转类型 tolua_cast(button1, " Button")




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值