reid
reid

Reputation: 552

How to pass an object of anonymous functions to another object?

I am trying to create a bunch of callback functions that are in an Associative Array, which then is saved to another Scenegraph object's interface field.

However, when accessing the interface field in the same object, it states that the function is invalid.

Object 1:

callbacks = {
    afterchildcreatecallback: function ()
      print "THIS IS A CALLBACK FUNCTION"
      return 1
    end function
  }

  m.contentReader = createObject("roSGNode", "ContentReader")
  m.contentReader.observeField("content", "setLists")
  m.contentReader.contenturi = "pkg:/data/contentLists/" + settingFocused.id + "Data.xml"
  m.contentReader.callbacks = callbacks
  m.contentReader.control = "RUN"

Object 2:

<component name = "ContentReader" extends = "Task" >
  <script type = "text/brightscript" uri="pkg:/components/taskRunners/contentReader.brs"></script>

  <interface>
    <field id = "contenturi" type = "uri"></field>
    <field id = "content" type = "node"></field>
    <field id = "callbacks" type = "assocarray"></field>
  </interface>

</component>

When accessing the callbacks field in Object 2, I can see the added object but the function that was defined inside it, is invalid.

Is this allowed? Or do I have to pass the function through a setter method?

Upvotes: 0

Views: 982

Answers (1)

Alejandro Cotilla
Alejandro Cotilla

Reputation: 2621

You can't store functions in a interface associative array field. That's either a BrightScript limitation or a design feature. If you want to use a listener-callback pattern, you can still do so using interface functions through callFunc().

YourNode.xml

<component name="YourNode" extends="Node">
  <interface>
    <function name="myCallback"/>
  </interface>
</component>

YourNode.brs

sub init()
  m.contentReader = createObject("roSGNode", "ContentReader")
  m.contentReader.listener = m.top
  (...)
end sub

sub myCallback(params)
  ?"params "params
end sub

ContentReader.xml

<component name="ContentReader" extends="Task">
  <interface>
    (...)
    <field id="listener" type="node"/>
  </interface>
</component>

ContentReader.brs

sub onTaskDone()
  params = ...
  m.top.listener.callFunc("myCallback", params)
end sub

Also, make sure to "release" the listener reference after you're done with it, you can do that from YourNode by doing m.contentReader.listener = invalid. This would avoid memory leaks caused by circular references.

Upvotes: 2

Related Questions