Cocos2dx中如何使用Lua-binding

Cocos2dx中使用Lua-binding

什么是lua-binding?

把c++代码封装成c函数,调用lua c api,实现对栈空间的操作,将c++的数据传递给lua。lua脚本加载好c++库,就可以自由调用c++里面的类对象和成员函数。这个过程叫做lua-binding。
在这里插入图片描述

为什么会有lua-binding?

  • c++具有高性能和跨平台系统兼容的优势。
  • Lua做为轻量级的脚本语言,可以提供便捷的开发效率。
  • 如何结合两种语言的优势,实现混合开发?lua-binding的出现就是为了解决这个问题。

cocos2dx中使用lua-binding

我们一起看看cocos2dx引擎的源码来了解完整的lua-binding流程。
先了解一下几种需要关注的文件
cocos文件夹下的C++代码,这是引擎的具体实现

cocos文件夹里存放的是引擎c++实现
tools/tolua/genbindings.py 这是生成LuaC的脚本
tools/tolua/*.ini 这是生成LuaC的配置文件
cocos/scripting/auto中是生成的luaC文件

大概过程就是通过genbindings.py脚本和*.ini配置文件把C++代码编程成luaC,然后在把生成的luaC注册到lua堆栈中,这样就可以在lua中调用C++的方法。

接下来看一个具体的例子,我们在lua中调用的cc.Director是如何进行lua-binding的?
Director的C++实现是在cocos/base文件夹下
CCDirector的头文件在cocos/cocos2d.h被引用
然后在tools/tolua/cocos2dx.ini中配置了cocos2d.h和Director类
这里先关注几个配置
[cocos2d-x] 这个配置将会在genbindings.py中提及
target_namespace = cc 这是目标命名空间,也就是为什么我们在lua中使用Director时前面要加上cc
headers 表示要引入的头文件,可以看到这里引入了cocos2d.h
classes 哪些类需要进行编译,可以看到除了Director类还有其它类
skip 剔除类里面的某些方法不进行编译

[cocos2d-x]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = cocos2dx

# create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`)
# all classes will be embedded in that namespace
target_namespace = cc

android_headers = 

android_flags = -target armv7-none-linux-androideabi -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -DANDROID -D__ANDROID_API__=14 -gcc-toolchain %(gcc_toolchain_dir)s --sysroot=%(androidndkdir)s/platforms/android-14/arch-arm  -idirafter %(androidndkdir)s/sources/android/support/include -idirafter %(androidndkdir)s/sysroot/usr/include -idirafter %(androidndkdir)s/sysroot/usr/include/arm-linux-androideabi -idirafter %(clangllvmdir)s/lib64/clang/5.0/include -I%(androidndkdir)s/sources/cxx-stl/llvm-libc++/include

clang_headers = 
clang_flags = -nostdinc -x c++ -std=c++11 -fsigned-char -U__SSE__

cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/external
cocos_flags = -DANDROID

cxxgenerator_headers =

# extra arguments for clang
extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s

# what headers to parse
headers = %(cocosdir)s/cocos/cocos2d.h %(cocosdir)s/cocos/2d/CCProtectedNode.h %(cocosdir)s/cocos/base/CCAsyncTaskPool.h %(cocosdir)s/cocos/scripting/lua-bindings/manual/CCComponentLua.h %(cocosdir)s/cocos/renderer/CCRenderer.h %(cocosdir)s/cocos/renderer/CCPipelineDescriptor.h 

# what classes to produce code for. You can use regular expressions here. When testing the regular
# expression, it will be enclosed in "^$", like this: "^Menu*$".
classes = New.* Sprite.* Scene Node.* Director Layer.* Menu.* Touch .*Action.* Move.* Rotate.* Blink.* Tint.* Sequence Repeat.* Fade.* Ease.* Scale.* Transition.* Spawn Animat.* Flip.* Delay.* Skew.* Jump.* Place.* Show.* Progress.* PointArray ToggleVisibility.* RemoveSelf Hide Particle.* Label.* Atlas.* TextureCache.* Texture2D Cardinal.* CatmullRom.* ParallaxNode TileMap.* .*TMX.* CallFunc RenderTexture GridAction Grid3DAction GridBase$ .+Grid Shaky3D Waves3D FlipX3D FlipY3D Speed ActionManager Set Scheduler Timer Orbit.* Follow.* Bezier.* CardinalSpline.* Camera.* DrawNode .*3D$ Liquid$ Waves$ ShuffleTiles$ TurnOffTiles$ Split.* Twirl$ FileUtils$ GLProgram ShaderCache Application ClippingNode MotionStreak ^Ref$ UserDefault GLViewImpl GLView Image Event(?!.*(Physics).*).* Component ProtectedNode Console GLProgramCache GLProgramState Device ClippingRectangleNode .*Light$ AsyncTaskPool RenderState Material Properties Technique Pass PolygonInfo AutoPolygon BoneNode SkeletonNode ComponentLua PipelineDescriptor Renderer FastTMXLayer FastTMXTiledMap

# what should we skip? in the format ClassName::[function function]
# ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also
# regular expressions, they will not be surrounded by "^$". If you want to skip a whole class, just
# add a single "*" as functions. See bellow for several examples. A special class name is "*", which
# will apply to all class names. This is a convenience wildcard to be able to skip similar named
# functions from all classes.

skip = Node::[setGLServerState description getUserObject .*UserData getGLServerState .*schedule getPosition$ setContentSize setAnchorPoint enumerateChildren getonEnterTransitionDidFinishCallback getOnEnterCallback getOnExitCallback getonExitTransitionDidStartCallback setAdditionalTransform setRotationQuat getRotationQuat sortNodes],
        Sprite::[getQuad ^setPosition$ ^create$ setPolygonInfo initWithPolygon getPolygonInfo],
        SpriteFrame::[setPolygonInfo getPolygonInfo hasPolygonInfo],
        SpriteBatchNode::[getDescendants],
        MotionStreak::[draw update],
        ParticleSystem::[updateQuadWithParticle initParticle],
        DrawNode::[drawPolygon drawSolidPoly drawPoly drawCardinalSpline drawCatmullRom drawPoints listenBackToForeground],
        Director::[getAccelerometer getProjection getFrustum getCocos2dThreadId],
        Layer.*::[didAccelerate keyPressed keyReleased],
        Menu.*::[.*Target getSubItems create initWithItems alignItemsInRows alignItemsInColumns],
        MenuItem.*::[create setCallback initWithCallback],
        Label::[createWithTTF],
        Copying::[*],
        LabelProtocol::[*],
        LabelTextFormatProtocol::[*],
        .*Delegate::[*],
        PoolManager::[*],
        Texture2D::[setTexParameters initWithData getPixelFormatInfoMap updateWithData initWithMipmaps],
        Set::[begin end acceptVisitor],
        IMEDispatcher::[*],
        SAXParser::[*],
        Thread::[*],
        Profiler::[*],
        ProfilingTimer::[*],
        CallFunc::[create initWithFunction],
        SAXDelegator::[*],
        Color3bObject::[*],
        TouchDispatcher::[*],
        EGLTouchDelegate::[*],
        ScriptEngineManager::[*],
        KeypadHandler::[*],
        Invocation::[*],
        SchedulerScriptHandlerEntry::[*],
        Size::[*],
        Point::[*],
        PointArray::[*],
        Rect::[*],
        String::[*],
        Data::[*],
        Dictionary::[*],
        Array::[*],
        Range::[*],
        EventListenerVector::[*],
        EventListener.*::[create],
        EventTouch::[(s|g)etTouches],
        NotificationObserver::[*],
        Image::[initWithString initWithImageData initWithRawData getData getMipmaps],
        Sequence::[create],
        Spawn::[create],
        GLProgram::[getProgram setUniformLocationWith2f.* setUniformLocationWith1f.* setUniformLocationWith3f.* setUniformLocationWith4f.* setUniformLocationWithMatrix4f.* getUniform setUniformLocationWith3i.* setUniformLocationWith4i.* setUniformLocationWith2i.* setUniformLocationWithMatrix3f.* setUniformLocationWithMatrix2f.* getVertexAttrib],
        Grid3DAction::[create actionWith.* vertex originalVertex (g|s)etVertex getOriginalVertex],
        Grid3D::[vertex originalVertex (g|s)etVertex getOriginalVertex],
        TiledGrid3DAction::[create actionWith.* tile originalTile getOriginalTile (g|s)etTile],
        TiledGrid3D::[tile originalTile getOriginalTile (g|s)etTile],
        TMXLayer::[getTiles getTileGIDAt setTiles],
        FastTMXLayer::[(g|s)etTiles getTileGIDAt],
        TMXMapInfo::[startElement endElement textHandler],
        ParticleSystemQuad::[postStep setBatchNode draw setTexture$ setTotalParticles updateQuadWithParticle setupIndices listenBackToForeground initWithTotalParticles particleWithFile node],
        LayerMultiplex::[create layerWith.* initWithLayers],
        CatmullRom.*::[create actionWithDuration],
        Bezier.*::[create actionWithDuration],
        CardinalSpline.*::[create actionWithDuration setPoints],
        Scheduler::[pause resume unschedule schedule update isTargetPaused isScheduled performFunctionInCocosThread],
        TextureCache::[addPVRTCImage addImageAsync],
        Timer::[getSelector createWithScriptHandler],
        *::[copyWith.* onEnter.* onExit.* ^description$ getObjectType (g|s)etDelegate onTouch.* onAcc.* onKey.* onRegisterTouchListener],
        FileUtils::[getFileData getDataFromFile writeDataToFile getFullPathCache getContents],
        Application::[^application.* ^run$],
        Camera::[getEyeXYZ getCenterXYZ getUpXYZ],
        ccFontDefinition::[*],
        Ref::[autorelease isEqual acceptVisitor update],
        UserDefault::[getInstance (s|g)etDataForKey],
        GLView::[setTouchDelegate getAllTouches],
        GLViewImpl::[end swapBuffers],
        NewTextureAtlas::[*],
        DisplayLinkDirector::[mainLoop setAnimationInterval startAnimation stopAnimation],
        RenderTexture::[listenToBackground listenToForeground newImage],
        TMXTiledMap::[getPropertiesForGID],
        EventCustom::[getUserData setUserData],
        Component::[serialize],
        Console::[addCommand addSubCommand getSubCommand delSubCommand getCommand],
        ParallaxNode::[(s|g)etParallaxArray],
        TileMapAtlas::[(s|g)etTGAInfo],
        GLProgramState::[setVertexAttribCallback setUniformCallback setVertexAttribPointer],
        OrbitCamera::[sphericalRadius],
        ShuffleTiles::[placeTile shuffle],
        TurnOffTiles::[shuffle],
        LabelTTF::[*],
        LabelBMFont::[*],
        Scene::[getCameras getLights .*(Physics3D).* .*(NavMesh).*],
        Animate3D::[*],
        Sprite3D::[*],
        AttachNode::[*],
        Animation3D::[*],
        Skeleton3D::[*],
        Mesh::[*],
        Animation3DCache::[*],
        Sprite3DMaterialCache::[*],
        Sprite3DMaterial::[*],
        Sprite3DCache::[*],
        Bone3D::[*],
        Device::[getTextureDataForText],
        BillBoard::[*],
        Camera::[unproject],
        EventListenerCustom::[init],
        EventListener::[init],
        RotateTo::[calculateAngles],
        RenderState::[finalize setStateBlock getStateBlock],
        Properties::[createNonRefCounted],
        AutoPolygon::[trace reduce expand triangulate calculateUV generateTriangles generatePolygon],
        PolygonInfo::[operator=],
        Technique::[getStateBlock],
        Material::[getStateBlock setStateBlock],
        Pass::[getStateBlock]

rename_functions = SpriteFrameCache::[addSpriteFramesWithFile=addSpriteFrames getSpriteFrameByName=getSpriteFrame],
    ProgressTimer::[setReverseProgress=setReverseDirection],
    AnimationCache::[addAnimationsWithFile=addAnimations],
    GLProgram::[setUniformLocationWith1i=setUniformLocationI32],
    Node::[removeFromParentAndCleanup=removeFromParent removeAllChildrenWithCleanup=removeAllChildren],
    LabelAtlas::[create=_create],
    Touch::[getID=getId],
    FileUtils::[loadFilenameLookupDictionaryFromFile=loadFilenameLookup],
    Director::[end=endToLua],
    GLView::[end=endToLua],
    RenderTexture::[end=endToLua]

rename_classes = ParticleSystemQuad::ParticleSystem

# for all class names, should we remove something when registering in the target VM?
remove_prefix =

# classes for which there will be no "parent" lookup
classes_have_no_parents = Director FileUtils TMXMapInfo Application Downloader

# base classes which will be skipped when their sub-classes found them.
base_classes_to_skip = Clonable

# classes that create no constructor
# Set is special and we will use a hand-written constructor
abstract_classes = Action FiniteTimeAction ActionInterval ActionEase EaseRateAction EaseElastic EaseBounce ActionInstant GridAction Grid3DAction TiledGrid3DAction Director SpriteFrameCache TransitionEaseScene Set FileUtils Application ClippingNode Label GLViewImpl GLView EventAcceleration DisplayLinkDirector Component Console EventListener BaseLight

# Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.
script_control_cpp = no

然后我们看genbindings.py文件
output_dir是编译好的luaC文件的输出路径
然后可以看到 ‘cocos2dx.ini’ : (‘cocos2d-x’, ‘lua_cocos2dx_auto’), 这表示编译的时候要使用cocos2dx.ini配置文件,cocos2d-x与cocos2dx.ini文件中的第一行对应,lua_cocos2dx_auto是编译后的文件名
在这里插入图片描述

然后可以看到cocos/scripting/lua-bindings/auto下有了lua_cocos2dx_auto文件。
这个文件中有一个register_all_cocos2dx方法,这个方法会在LuaStack::init()里被调用,这样就会在lua堆栈初始化的时候把C++的类和方法注册进去,我们就可以在lua中调用这些方法了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值