3

I am trying to translate a piece of code I wrote from Python to Lua. I am using this code inside of compositing package Blackmagic Fusion.

Any help would be greatly appreciated!

Python script (working):

try:
    comp.ActiveTool()                            # checks if a tool is selected
except:
    print("nothing selected")
    comp.AddTool("PolylineMask", -32768, -32768) # adds a tool if nothing's selected

Lua script (still not working and erroring):

if pcall (comp:ActiveTool()) then
    print "Node Selected"
else
   comp:AddTool("PolylineMask", -32768, -32768)
end
Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
iGwok
  • 323
  • 5
  • 18

4 Answers4

7

Lua's exception handling works a bit differently than in other languages. Instead of wrapping code in try/catch statements, you instead run a function in a 'protected environment' with pcall.

The general syntax for pcall is:

local ok, err = pcall(myfunc, arg1, arg2, ...)
if not ok then
    print("The error message was "..err)
else
    print("The call went OK!")
end

Where myfunc is the function you want to call and arg1 and so on are the arguments. Note that you aren't actually calling the function, you are just passing it so that pcall can call it for you.

BUT keep in mind that tbl:method(arg1, arg2) in Lua is syntax sugar for tbl.method(tbl, arg1, arg2). However, since you aren't calling the function yourself, you can't use that syntax. You need to pass in the table to pcall as the first argument, like so:

pcall(tbl.method, tbl, arg1, arg2, ...)

Thus, in your case it would be:

local ok, err = pcall(comp.ActiveTool, comp)
Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85
1

You aren't using pcall correctly. you need to pass it the function you actually want called, and it'll call it in a protected mode where it can trap errors.

pcall returns 2 values, a bool indicating if the call succeeded or not, and an error code if the call did not succeed.

your lua code should look more something like this:

local ok, err = pcall(comp.ActiveTool, comp)
if not ok then
    print(err, 'nothing selected')
    comp.AddTool(...)
else -- the call succeeded
    print 'Node Selected'
end

and in the case that you want to call functions using pcall that take params, you can simply pass them as additional values to pcall, and it'll pass those on to the method you gave it when it calls it.

local ok, err = pcall(comp.AddTool, 'PolylineMask', -32768, -32768)

as an example.

the above line roughly translates to:

try {
    comp.AddTool('PolylineMask', -32768, -32768);
    return true
} 
catch (err) {
    return false, err
}
Mike Corcoran
  • 14,072
  • 4
  • 37
  • 49
  • thanks for the quick response. I am still struggling to figure out what is going on here. I have updated the Lua code, but it is still erroring. Instead of erroring, I want it to run this piece of code "comp.AddTool('PolylineMask', -32768, -32768)". The error message I am getting is "attempt to call method 'ActiveTool' (a nil value)" – iGwok Jul 24 '13 at 17:33
  • 1
    the error you state is simply lua saying that the `comp` object doesn't have a function/property available on it called `ActiveTool`. there could be several reasons for that. without seeing more code related to the `comp` object, i can't help you with that issue. – Mike Corcoran Jul 24 '13 at 17:35
  • @user2528059, Guessing what you're trying to do, you might use `local ok,err; if comp.ActiveTool then ok,err = false,"" else ok,err = pcall(comp:ActiveTool) end` ... – Doug Currie Jul 24 '13 at 21:52
  • Should be `pcall(comp.ActiveTool, comp)`, not `pcall(comp:ActiveTool)` – Paul Kulchenko Jul 24 '13 at 23:03
  • @PaulKulchenko thanks, fixed. been a little while since i've worked in Lua =/ – Mike Corcoran Jul 25 '13 at 13:59
1

Note the difference:

pcall (foo())
pcall (foo)

The first line calls the function foo then passes its result to pcall. If foo throws an error, pcall will never be called.

The second line passes the function foo to pcall. pcall calls foo. If foo throws an error pcall captures it and returns an error message.


In your example, you're making a method call, where comp:ActiveTool() is syntax sugar for comp.ActiveTool(comp) so you'll have to take that into consideration when calling pcall: comp:ActiveTool() => pcall(comp.ActiveTool, comp).

Mud
  • 28,277
  • 11
  • 59
  • 92
  • 1
    this won't work. You need to use `comp.ActiveTool` and pass `comp` as a parameter as well (to emulate `comp:ActiveTool()` call). – Paul Kulchenko Jul 24 '13 at 23:01
  • @PaulKulchenko Oops. Yeah, I was focused on the difference between passing a function or its result to pcall. Changed example to focus on that, then clarified about method calls below. – Mud Jul 25 '13 at 15:22
0
-- test.lua
require "try-catch"

try {
   function ()
      error('oops')
   end,

   catch {
      function (error)
         print('caught error: ' .. error)
      end
   }
}

...

-- try-catch.lua
function catch (what)
   return what[1]
end

function try (what)
   status, result = pcall(what[1])

   if not status then
      what[2](result)
   end

   return result
end

Original https://gist.github.com/cwarden/1207556

Alexander Abashkin
  • 1,187
  • 4
  • 13
  • 18