CCCallFunc call a function of a lua class instance

Hi,

I have a class in Lua called Reel with the following function:

function Reel:didCompleteFixAnimation()
self.x = self.x + 1
end

I am passing the function to CCCallFunc in another class method like so:

local animationAction = CCMoveTo:create(_fixReelAnimationDuration, point)
local callbackAction = CCCallFunc:create(self.didCompleteFixAnimation)
local actions = CCSequence:createWithTwoActions(animationAction, callbackAction)
sprite:runAction(actions)

didCompleteFixAnimation does get called after the completion of the action sequence, however the reference to ‘self’ is nil. I get the following error message:

reel.lua:145: attempt to index local ‘self’ (a nil value)

Is there a way I can get the reference to self?

To answer my own question, I ended up having to extend CCCallFunc with a static method createWithTable that accepts a table and a function as a parameter, I call it like this:

local callbackAction = CCCallFunc:createWithTable(self, self. didCompleteFixAnimation)

The github commit is here in case anyone else needs to have CCCallFunc call a Lua function and pass a table as an argument:

Hi,

I have another way to pass parameter to CCCallFunc.

-- To read easier, I write a function looks like schedule once.
function performWithDelay(node, callback, delay)
    local delay = CCDelayTime:create(delay)
    local callfunc = CCCallFunc:create(callback)    
    local sequence = CCSequence:createWithTwoActions(delay, callfunc)
    node:runAction(sequence)
    return sequence
end

-- Solution is in callback function. I use parent function save parameters, use child function as main functionality.
function changeScene(...)               
        local args = ...
        local ret = function ()
            -- body            
            local aboutGame = args.screen.create()
            CCDirector:sharedDirector():replaceScene(aboutGame)
        end
        return ret        
end

-- Finally, here is a usage.
performWithDelay(sceneGame, changeScene({screen=aboutscreen}), 1)

Based on original idea, we can improve performWithDelay function as below:

-- wrapper for callback with arguments
function callbackWithArgs(callback, args)
    local params = args
    local ret = function ()
    -- body
        callback(args)
    end
    return ret
end

-- performWithDelay version 2
function performWithDelay(node, callback, delay, args)
    local delay = CCDelayTime:create(delay)
    local callfunc = CCCallFunc:create(callbackWithArgs(callback, args)
    local sequence = CCSequence:createWithTwoActions(delay, callfunc)
    node:runAction(sequence)
    return sequence
end

-- your callback will be simple
function changeScene(args)
    -- body
    local aboutGame = args.screen.create()
    CCDirector:sharedDirector():replaceScene(aboutGame)
end

-- Finally, here is a usage.
performWithDelay(sceneGame, changeScene, 1, {screen=aboutscreen})

in fact, a simple __bind function is enough for such case

function __bind(fn, obj)
return function(…)
return fn(obj, …)
end
end

CCCallFunc:create( __bind(self.didCompleteFixAnimation, self) )

In the v3.0,the lua binding of CallFunc::create can support two param,and the second param is a “Node” lua object.