Home AMX User Forum NetLinx Studio

Structure array in button_event

Has anyone tried something similar to what I was trying today? I tried to use an array inside a structure to trigger a button_event. Eg:
button_event[dvUI, strStruct.array]
{
  push:
  {
    stack_var integer channel
    channel = get_last(strStruct.array)
  }
}
I couldn't get it to work properly. The button gets fired but the button event never gets run.
Thanks,
Paul

Comments

  • Joe HebertJoe Hebert Posts: 2,159
    Interesting concept

    I haven't tried it before and I can't test it at the moment but if it resolves to an integer array I would think it should work. Did you do a REBUILD_EVENT() after you initialized your structure?
    a_riot42 wrote: »
    Has anyone tried something similar to what I was trying today? I tried to use an array inside a structure to trigger a button_event. Eg:
    button_event[dvUI, strStruct.array]
    {
      push:
      {
        stack_var integer channel
        channel = get_last(strStruct.array)
      }
    }
    
    I couldn't get it to work properly. The button gets fired but the button event never gets run.
    Thanks,
    Paul
  • a_riot42a_riot42 Posts: 1,624
    Joe Hebert wrote: »
    I haven't tried it before and I can't test it at the moment but if it resolves to an integer array I would think it should work. Did you do a REBUILD_EVENT() after you initialized your structure?

    Yes I did. The array is populated using a for loop in define_start and after the for loop I call rebuild_event. Didn't make any difference though.
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote: »
    The array is populated using a for loop in define_start and after the for loop I call rebuild_event.
    Did you populate by setting individual elements in the array? If so you''ll need to call SET_LENGTH_ARRAY()
  • a_riot42a_riot42 Posts: 1,624
    Joe Hebert wrote: »
    Did you populate by setting individual elements in the array? If so you''ll need to call SET_LENGTH_ARRAY()

    The array length is set in the declaration so I saw no need to use set_length_array. Is there something special about arrays inside structures that requires it?

    As an aside, I also tried it with an array of structures with only one element and surprisingly netlinx lets you use either the array notation [] or not. So both structure[1].array and structure.array compile. I wonder if that works with arrays not inside structures too, I have never thought to try.
    Thanks,
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote:
    Has anyone tried something similar to what I was trying today? I tried to use an array inside a structure to trigger a button_event.
    I tried it and it works fine as the following demonstrates:
    DEFINE_DEVICE
    
    dvTP = 10001:1:0
    
    DEFINE_TYPE
    
    STRUCT _sGUIDef {
       INTEGER Buttons[4]
    }
    
    DEFINE_VARIABLE
    
    _sGUIDef  sGUIDef
    INTEGER x
    
    DEFINE_START
    
    //create buttons 2, 4, 6, and 8
    FOR (x=1; x<=4; x++) {
       sGUIDef.Buttons[x] = x*2
    }
    
    //we have to manually set the length or rebuild won't get us anything
    SET_LENGTH_ARRAY(sGUIDef.Buttons,4)
    
    //rebuild the event table
    REBUILD_EVENT()
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,sGUIDef.Buttons] {
       PUSH: {
          SEND_STRING 0,"'BUTTON.INPUT.CHANNEL = ',ITOA(BUTTON.INPUT.CHANNEL)"
          SEND_STRING 0,"'GET_LAST(sGUIDef.Buttons) = ',ITOA(GET_LAST(sGUIDef.Buttons))"
       }
       
    }
    

    Pushing buttons 2, 4, 6, and 8 produces the following output:
    Line      1 :: BUTTON.INPUT.CHANNEL = 2 - 22:21:27
    Line      2 :: GET_LAST(sGUIDef.Buttons) = 1 - 22:21:27
    Line      3 :: BUTTON.INPUT.CHANNEL = 4 - 22:21:30
    Line      4 :: GET_LAST(sGUIDef.Buttons) = 2 - 22:21:30
    Line      5 :: BUTTON.INPUT.CHANNEL = 6 - 22:21:32
    Line      6 :: GET_LAST(sGUIDef.Buttons) = 3 - 22:21:32
    Line      7 :: BUTTON.INPUT.CHANNEL = 8 - 22:21:35
    Line      8 :: GET_LAST(sGUIDef.Buttons) = 4 - 22:21:35
    
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote:
    The array length is set in the declaration so I saw no need to use set_length_array.
    The max length is set in the declaration not the actual/current length.
    a_riot42 wrote:
    Is there something special about arrays inside structures that requires it?
    Nope, not anything special. There is a difference in that you can?t initialize an array inside a structure as you declare it which is why the length is zero.

    If you do this (inside or outside a structure):

    INTEGER nArray[10]

    The length is 0.

    If you do this (can only do this outside a structure):

    INTEGER nArray[] = {1,2,3,4,5}

    The length is 5.
  • a_riot42a_riot42 Posts: 1,624
    Sounds like there are some gotchas there. I ended up getting the button_event to run even without doing set_length_array but get_last always returned 0 on the array in the event. I don't understand how the button_event could run if I didn't use set_length_array since the length of the array would be 0 and thus any integer in the array wouldn't trigger the event. Definitely some weird business going on underneath the hood.

    Weird that arrays are dealt with so differently depending on how they are declared and if they are in a structure.
    Thanks,
    Paul
  • DHawthorneDHawthorne Posts: 4,584
    I'm inclined to question if structures are supported at all in button events. I've never tried it myself, and would probably avoid putting myself in a position where I felt I had to. I just use straight arrays.
  • ericmedleyericmedley Posts: 4,177
    DHawthorne wrote: »
    I'm inclined to question if structures are supported at all in button events. I've never tried it myself, and would probably avoid putting myself in a position where I felt I had to. I just use straight arrays.

    I've used them in B_Es before but not for dealing with identifying the event itself.

    I must admit that I rarely use Structures myself. I just use arrays made the old fashioned way. I've never quite understood the functional difference really.
  • a_riot42a_riot42 Posts: 1,624
    ericmedley wrote: »
    I've used them in B_Es before but not for dealing with identifying the event itself.

    I must admit that I rarely use Structures myself. I just use arrays made the old fashioned way. I've never quite understood the functional difference really.

    This is what I have had to do, since structure support seems woefully incomplete. But often times it makes sense to use a structure to create an entity of data that belongs together, and there is no technical reason why an array in a structure can't be used to trigger a button_event just as any other array so it should be fine. There are some good reasons to use structures in order to write more abstract code, but it doesn't look like its as reliable as I had hoped.
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote:
    I ended up getting the button_event to run even without doing set_length_array but get_last always returned 0 on the array in the event.
    How did you manage that? :) Care to post the code? If I comment out SET_LENGTH_ARRAY() the button event never fires.
    a_riot42 wrote:
    Weird that arrays are dealt with so differently depending on how they are declared and if they are in a structure.
    AFAIK, arrays are dealt with exactly the same way whether in a structure or not. The rules are consistent and I would expect them to be so. You can?t use an initializer while declaring an array inside a structure but it?s not because it?s an array. It?s because initializers can only be used in the DEFINE_CONSTANT and DEFINE_VARIABLE sections. I?m not sure why DEFINE_TYPE is excluded.

    We can do this:
    DEFINE_VARIABLE
    INTEGER nZone = 1
    

    But we can?t do this:
    DEFINE_TYPE
    STRUCT _sTPInfo {
       // can't do this:
       INTEGER CurrentZone = 1 //initialize to valid zone number
    } 
    

    We can only do this:
    DEFINE_TYPE
    STRUCT _sTPInfo {
          INTEGER CurrentZone
    } 
    

    Netlinx will set CurrentZone to 0 by default when any instance of the struct is instantiated. Seems to me it would be just as painless to plug a value of 1 in there for us instead. Easy for me to say as I?m not the one writing the compiler/OS. :)
    DHawthorne wrote:
    I'm inclined to question if structures are supported at all in button events. I've never tried it myself, and would probably avoid putting myself in a position where I felt I had to. I just use straight arrays.
    I?ve always used straight arrays for buttons also but structures seem to be supported without issue as the code I posted earlier demonstrates.
    a_riot42 wrote:
    there is no technical reason why an array in a structure can't be used to trigger a button_event just as any other array so it should be fine. There are some good reasons to use structures in order to write more abstract code, but it doesn't look like its as reliable as I had hoped.
    As the risk of sounding like a broken record, it does work and I?ll consider it reliable until proven otherwise. As long as one understands the rules of arrays, there shouldn?t be a problem.

    I use structures extensively but as stated earlier I?ve never used them for channel codes. Thanks for bringing this idea to the surface as it may come in handy sometime down the road.
  • a_riot42a_riot42 Posts: 1,624
    Joe Hebert wrote: »
    How did you manage that? :) Care to post the code? If I comment out SET_LENGTH_ARRAY() the button event never fires.

    Tomorrow I can.
    Joe Hebert wrote: »
    AFAIK, arrays are dealt with exactly the same way whether in a structure or not. The rules are consistent and I would expect them to be so. You can?t use an initializer while declaring an array inside a structure but it?s not because it?s an array. It?s because initializers can only be used in the DEFINE_CONSTANT and DEFINE_VARIABLE sections. I?m not sure why DEFINE_TYPE is excluded.

    I wasn't trying to use an initializer. I was initing the variables in define_start. Tech support mentioned nothing about set_length_array and in the example code for string _to_variable in the docs, they don't use it either and just init the variables in define_start like I was doing.
    Joe Hebert wrote: »
    As the risk of sounding like a broken record, it does work and I?ll consider it reliable until proven otherwise. As long as one understands the rules of arrays, there shouldn?t be a problem.

    I usually think the other way around, because it isn't often I try and do something interesting and don't run into an AMX anomoly.
    Joe Hebert wrote: »
    I use structures extensively but as stated earlier I?ve never used them for channel codes. Thanks for bringing this idea to the surface as it may come in handy sometime down the road.

    It seemed to make sense to me at the time. However there are enough drawbacks to structures that make them less appealing like the inability to pass one to a module or return one from a function, and you can't use persistent on the contents.
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote:
    I was initing the variables in define_start. Tech support mentioned nothing about set_length_array and in the example code for string _to_variable in the docs, they don't use it either and just init the variables in define_start like I was doing.
    How were you defining the variables in define_start? That?s the key question and that will answer whether you need to use set_length_array or not. All you mentioned was using a FOR loop which is why I asked if you were assigning values to individual elements of the INTEGER array. I followed up by saying that if you are then set_length_array is needed and I posted code to demonstrate that.

    The STRING_TO_VARIABLE example in the Netlnx help file doesn?t use SET_LENGTH_ARRAY() because it doesn?t need it. The two 100 byte character arrays in the structure get their length set in DEFINE_START when direct assignment ( MyAlbumStruct[1].sArtist = 'Buffet, Jimmy') is used to fill in the arrays. After said assignment the length of MyAlbumStruct[1].sArtist is automatically set to 13.

    Had the example done something silly (for a char array) like

    MyAlbumStruct[1].sArtist[1] = 'B?
    MyAlbumStruct[1].sArtist[2] = 'u?
    ???
    MyAlbumStruct[1].sArtist[13] = 'y?

    Then the length would have remained at 0 and a manual set length is needed.
    a_riot42 wrote:
    It seemed to make sense to me at the time. However there are enough drawbacks to structures that make them less appealing like the inability to?
    a_riot42 wrote:
    pass one to a module?
    Yes, I too along with many others I?m sure see that as a drawback. Heck, I?ve always been confused as to why we can?t pass anything (a straight integer, a constant, a string literal) into a module without being forced to create a variable for it first. I?ve been using the encode/decode methods described in the forums here to pass module data back and forth via structures and it works well. Granted it requires a bit more coding and additional overhead but it?s a workaround I?ve been able to accept and deal with. For me the tradeoff is well worth it.
    a_riot42 wrote:
    or return one from a function?
    Technically you can by passing the structure container in as a parameter. Since parameters to functions are passed in by reference it?s easy enough to accomplish a return. Instead of creating a structure in the function and then RETURN it you just have to modify the struct that was passed in. The RETURN value can then be used as some sort of error code to signify success or failure.
    a_riot42 wrote:
    and you can't use persistent on the contents.
    That?s not true. You can use the PERSISTENT keyword when instantiating a STRUCTURE in DEFINE_VARIABLE. I?ve used persistent structures before and they work fine. It?s an all or nothing deal though. You have to declare the entire structure as PERSISTENT and not just individual elements. Maybe that?s what you are referring to? I?ve been moving away from the PERSISTENT keyword and leaning more towards writing to disk.

    What you can?t do is use PERSISTENT in a module but that?s a limitation of modules themselves, not structures.

    I personally would find Netlinx way less appealing as a language sans structures. I admit that my current contract includes an incentive bonus for every person that I convert to Structurism. So naturally I?m inclined to say, ?Try it. You?ll like it? as I?m paid to spread the word. :)
Sign In or Register to comment.