Home AMX User Forum NetLinx Studio

Function pointers

One thing that Netlinx is missing that I miss from C is function pointers. Has anyone tried to implement something similar? I could use it in this job where I have 100 functions that will activate any one of 10 devices in 10 zones. So for device 1 which is a DVD I have 10 functions, one for each of the 10 zones. ie: kitchenDVD, mBedDVD, livingDVD etc.

However, if I want to start the DVD in all 10 rooms at once, I have to write a switch that takes the zone and then calls the appropriate function for each zone.
if (device == DVD)
{
  switch(output)
  {
    case mBed:
    {
      mBedDVD()
    }
    case kitchen:
    {
      kitchenDVD()
    }
    ...
    ...
  } 
}

if (device == DVR)
{
  switch(output)
  {
    case mBed:
    {
      mBedDVR()
    }
    case kitchen:
    {
      kitchenDVR()
    }
    ...
    ...
  }
}


Its alot of code to do something pretty basic.

What I would do in C, is have an array of 100 function pointers so that for each input/output combination I just call the function that the pointer in the array points to.
for (int i = 1;i <= 10;i++)
{
  call functionptrArray[i]    // approx in Netlinx
}

I can't figure out a way to do this in Netlinx because there are no pointers but I am wondering if someone has implemented something similar with virtuals, events etc?

I won't know at compile time what device/zones the user will choose, so I need a way at runtime to change the function that is called depending on the device and zone. I was hoping that there would be a better way than hard code all the function calls.
Thanks,
Paul

Comments

  • mpullinmpullin Posts: 949
    Whereas I too miss the presence of pointers in NetLinx, but I don't think you need them to improve your code example. Try making a single function that takes two integer parameters, one for the device and one for the zone, e.g.
    DEFINE_FUNCTION TURN_ON(INTEGER zone, INTEGER src){
         switch(src){
              case 1: // dvd player
                   switch(zone){
                        case 1: // bedroom?
                             // turn on bedroom DVD
                        break;
                   }
              break;
              case 2: // etc.
              break;
         }
    }
    
    Now you can create loops to make calls to that function if you wish.
  • a_riot42a_riot42 Posts: 1,624
    That was what I was trying to avoid. Doing it that way requires 100 different cases, which isn't too bad I suppose, but if I had 12 devices and 20 zones then I am now at 240 cases. Since every zone/device function requires turning different devices on or off I need 100 different functions to do every possible combination. I thought there might be a more compact way of doing this. Here is how I turn on say 10 zones to the DVD.
    /* pseudocode */
    
    button_event[dvTP, 100]
    {
      for (cnNumZones)
      {
        currentZone = currentZone + 1
        do_push(dvFamilyTP, 20)
      }
    }
    

    Right now I have it set up where my button events for devices contain a switch like so:
    button_event[dvTP, 20]
    {
      push:
      {
        switch(currentZone)
        {
          case cnMBed:
          {
            mBedDVD()
          }
          case cnKitchen:
          {
            kitchenDVD()
          }
          ...
          ...
       }
      }
    }
    

    Is it possible for the timing of the do_push and the increment of the currentZone variable to get screwed up such that the for loop finishes before the do_push gets executed? I assume button_events are executed on an as needed basis so you have no way of knowing exactly when (it terms of where the code is) it starts and finishes.
    Thanks,
    Paul
  • ColzieColzie Posts: 470
    I create structures. u_zone, u_display, u_source, etc., and initialize these upon startup with all the info I need (device, name, etc.). Then I can create functions (one for displays, one for dvds, etc., each taking parameters such as device (or device pointer?) as well as the command) to do things like

    send_string u_display[iDisplay].dv_device, iCmd
    or
    pulse[u_source[iSource].dv_device, iCmd].

    Doing it this way can eliminate a lot of switch/cases.
  • a_riot42a_riot42 Posts: 1,624
    Colzie wrote:
    I create structures. u_zone, u_display, u_source, etc., and initialize these upon startup with all the info I need (device, name, etc.). Then I can create functions (one for displays, one for dvds, etc., each taking parameters such as device (or device pointer?) as well as the command) to do things like

    send_string u_display[iDisplay].dv_device, iCmd
    or
    pulse[u_source[iSource].dv_device, iCmd].

    Doing it this way can eliminate a lot of switch/cases.


    Thanks, I do something similar, but the issue is that I want to call a function not send a string, command or pulse. I am guessing there is no way to do this other than come up with some other scheme. There doesn't seem to be a way to dynamically call different functions at runtime without hard coding it all.
    Paul
Sign In or Register to comment.