Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LUA: Call a function using its name (string) in a class

Tags:

function

oop

lua

I am trying to call a function of an object using its name (I would like to use the name because I will retrieve the function's name from an URL).

I am a beginner in LUA so I try to understand what is possible (or not!)

In this example I want to execute the function "creerCompte()" of the object "controllerUser" from my main file.

I have created a main file:

   --We create the controller object
   local controller = require("controllers/ControllerUser"):new()
   local stringAction = "creerCompte" -- Name of the function to call in the controller Object

   --Attempting to call the function stringAction of the object controller
   local action = controller:execute(stringAction)

This is the controller Object

ControllerUser = {}
ControllerUser.__index = ControllerUser

function ControllerUser:new()
    local o = {}
    setmetatable(o, self)
    return o
end

function ControllerUser:execute(functionName)
    loadstring("self:" .. functionName .. "()") --Doesn't work: nothing happens
    getfenv()["self:" .. functionName .. "()"]() --Doesn't work: attempt to call a nil value
    _G[functionName]() --Doesn't work: attempt to call a nil value
    self:functionName() -- Error: attempt to call method 'functionName' (a nil value)
end

function ControllerUser:creerCompte()
   ngx.say("Executed!") --Display the message in the web browser
end

return ControllerUser

Thanks in advance for any help

like image 477
Chewbye Avatar asked Dec 07 '22 00:12

Chewbye


2 Answers

Try self[functionName](self) instead of self:functionName().

self:method() is a shortcut for self.method(self) and self.method is syntactic sugar for self['method'].

like image 134
Paul Kulchenko Avatar answered Feb 06 '23 22:02

Paul Kulchenko


In Lua functions don't have a name. What you use as a name is either the name of a variable, or a key in a table (generally the global variables table)

If it's a global variable, you can certainly use _G['name'](args...), or _G[namevar](args...) if you have the name in the namevar variable. But this would easily break in a number of ways (doesn't work with local functions, or functions inside a module, etc.)

Much better (and safer) is to create a table with just those functions you want to make available, with the name you want to use as the key to the table:

local function doOneThing(args)
    -- anything here
end

local function someOtherThingToDo()
    -- ....
end

exportFuncs = {
    thing_one = doOneThing,
    someOtherThingToDo = someOtherThingToDo,
}

then, you can easily call the function from the name: exportFuncs[namevar](...)

like image 39
Javier Avatar answered Feb 06 '23 23:02

Javier