Home AMX User Forum AMX General Discussion

Length_array borken?

Length_array borken? Did I biff something here? This is on an NX-3200
DEFINE_VARIABLE

volatile _My_Struct My_Struct[5]

volatile integer My_3by_Integer[30][20][10]

DEFINE_EVENT

button_event[dv_test,1]{
	push:{
		send_string 0,"'toa(length_array(My_Struct))t is:',itoa(length_array(My_Struct)) "
		send_string 0,"'itoa(length_array(My_3by_Integer) is:',itoa(length_array(My_3by_Integer)) "
		send_string 0,"'itoa(length_array(My_3by_Integer[]) is:',itoa(length_array(My_3by_Integer[1])) "
		send_string 0,"'itoa(length_array(My_3by_Integer[][]) is:',itoa(length_array(My_3by_Integer[1][1])) "
		} // push
	} // b_e

Extended diagnostic information messages turned on.
(0000066232) toa(length_array(My_Struct))t is:0
(0000066233) itoa(length_array(My_3by_Integer) is:0
(0000066233) itoa(length_array(My_3by_Integer[]) is:0
(0000066234) itoa(length_array(My_3by_Integer[][]) is:0

Comments

  • ericmedleyericmedley Posts: 4,177
    Yep, and just to make sure I populated the vars with stuff. same result.

    Edited to add: Also just checked on an NI-900. same result.

    Edited again to add:
    Okay, now I made a global variable to load the value returned by length_array().

    here's what it returned. 65536
    seems like it might be a negative number (error code X) which is how AMX usually returns errors on functions. But, it's supposed to be a long return, not a slong or sinteeger. whatevers..

    but clearly its not working. This is really really bad for me since I use length_array() a lot to determine for loop lengths If I compile and old project a lot of my loops are going to stop working. This is bad.
  • GregGGregG Posts: 251
    I always use max_length_array() to get the length of arrays that have not been initialized.

    i.e.
    Define_Variable
    integer nArray1[10]
    integer nArray2[10] =
    {1,2,3,4,5,6,7,8,9,10}
    
    Array1 doesn't have a length, but max_length is 10
    Array2 has both set to 10
  • JasonSJasonS Posts: 229
    It has been my experience that on any array except a string you have to manually set the length of the array using "SET_LENGTH_ARRAY" or it will return 0.
  • ericmedleyericmedley Posts: 4,177
    Okay, so I just got off the phone with Tech Support and here's the dealio...

    We did indeed verify that it is not working as expected but it may well be that it was never intended to work the way "we" expected and it just kind of worked the way "we" expected until they fixed it some time ago.

    they are submitting this as a possible bug or at least reconsidering the idea that it should work the way we expected.

    In order to make length_array() work you must run a set_lenght_array() at runtime. Apparently this is where whatever length_array()'s function looks at for a value gets populated. My guess is that this is not thought through since you usually set the dimensions of an array in define_variable anyway. (either by hard code or by inference when you preset some value(s))

    I still have to suss out how set_length_array() deals with multi-dimensional arrays.

    but, anyway, that's the work-around/fix/using it the way it was intended to work/whatever.

    If they come back with more info I'll post here.
    Now, back to work.
    e
  • ericmedleyericmedley Posts: 4,177
    an addendum about the work-around.

    for multi-dimensional arrays you have to also run set_length_array() on each dimension.

    sor for example in the case of this sample

    volatile integer My_3by_Integer[30][20][10]

    you have to run these at startup:

    set_length_array(My_3by_Integer,30)
    set_length_array(My_3by_Integer[1],20)
    set_length_array(My_3by_Integer[1][1],10)
  • ericmedleyericmedley Posts: 4,177
    addendum to the addendum... :(

    the work around DOES NOT work for elements in a structure. So if you are doing any length_array(MyStruct[cell].MyArray) type stuff, you're hosed.
  • a_riot42a_riot42 Posts: 1,624
    I thought this was a problem only with structures, since they aren't initialized like integers, etc. I don't normally do 3 dimensional arrays of structures, but for an array in a structure, I use set_length_array in define_start. So for instance I have a structure with chars, ints, etc that get populated at start up, but the array in it needs to have its length set or the length will be zero.
    	for (zone = 1; zone <= cnNumAVZones; zone++)
    	{
    		stAVZones[zone].iVTChannel	 	= 10
    		stAVZones[zone].iSourceVTChannel 	= 11
    		stAVZones[zone].iSourceChannel 	= 20
    		stAVZones[zone].iSourceIndex		= 1
    		stAVZones[zone].dvSourceDevice	= vdvZoneOff
    		stAVZones[zone].sSourceName		= sSourceNames[1]
    		stAVZones[zone].sName			=	sZoneNames[zone]
    		stAVZones[zone].iAVMode			= cnWatch
    		stAVZones[zone].iRequestedAVMode	= cnWatch
    		stAVZones[zone].siMaxVolume		=	255
    		stAVZones[zone].siMinVolume		=	0
    		stAVZones[zone].siDefaultVolume	=	105
    		stAVZones[zone].siVolRampSpeed	= 10
    		stAVZones[zone].fPercentOfMax		= 0.8
    		[b]set_length_array(stAVZones[zone].dvUIs, cnNumUIs)[/b]
    	}
    
  • fcarfcar Posts: 1
    have you tried max_lenght_array
  • DHawthorneDHawthorne Posts: 4,584
    fcar wrote: »
    have you tried max_lenght_array

    That usually defeats the purpose. You know that already by the variable declaration (unless you are just trying to make it more portable, I suppose). LENGTH_ARRAY is to determine how populated it is at the moment, not how much it can hold total.
  • ericmedleyericmedley Posts: 4,177
    DHawthorne wrote: »
    That usually defeats the purpose. You know that already by the variable declaration (unless you are just trying to make it more portable, I suppose). LENGTH_ARRAY is to determine how populated it is at the moment, not how much it can hold total.

    Yes, and that's what is broken. Even if I popuplated the variable with stuff prior to running the function it produced a zero return. running the Set_Length_Array then makes it work. But, here again, you cannot run S_L_A on an element in an array of Structs. Not to be all pedantic - but the help says "All Instrinsic Variable Types" and more proctially, it's broke - fix it please.
  • GregGGregG Posts: 251
    The way it works currently is the way my code for the past few years has expected it to work.

    So how would we change it in a way that wouldn't break that code, ie:
    DEFINE_VARIABLE
    // I'd expect the length here to be 3
    Integer nActiveOutputList_1[50] = {1,2,3}
    
    // I'd expect it to be 0 here, but if we now make it 50, what would my code do ?
    Integer nActiveOutputList_2[50]
    
    // Example function that breaks if we change length_array from current:
    
    Define_Function TurnOffListedOutputs(Integer nList[])
    {
    Stack_Var Integer nItem
    
      For(nItem=1;nItem<=Length_Array(nList);nItem++)  // A Length_Array of 0, skips this loop
      {
    
        // What does this function do with the random garbage in nActiveOutputList_2 ?
        SwitchVideo(BLANK,nList[nItem])
    
      }
      Set_Length_Array(nList,0)
    }
    
  • well this is really Crap!

    I use length array for loads of stuff - they can't just change the operation of how this works after XX years of working in a specific manner with no notice.....They have to put a fix in place for this otherwise any code ported over to new controllers is screwed.
    Even if it wan't supposed to work in this manner and did, fixing it and effectively breaking it is a bit ridiculous. Although I suspect that it originally wasn't supposed to work in this way as Integer arrays have to have their length set..........

    Please fix!!!!!!!!!!!!!!!!!!!!
  • a_riot42a_riot42 Posts: 1,624
    ericmedley wrote: »
    addendum to the addendum... :(

    the work around DOES NOT work for elements in a structure. So if you are doing any length_array(MyStruct[cell].MyArray) type stuff, you're hosed.

    I am using it in this manner with success. I use set_length_array and then it works as expected for an array in a struct. I wonder if a array in a struct within a struct might not work, but I don't do that, since its slows processing so much, at least it used to.
    Paul
  • I'm confused.. As far as I know it has always worked this way, at least for as long as I can remember
    DEFINE_VARIABLE
    
    VOLATILE CHAR cArray1[10] = {'1','2','3'}
    //length = 3
    VOLATILE CHAR cArray2[10]
    //length = 0
    
    
    
    DEFINE_START
    
    cArray1 = "cArray1, '4','5','6'"
    //length is now 6
    
    cArray2[1] = 'A'
    cArray2[2] = 'B'
    cArray2[3] = 'C'
    //length is still 0
    
    cArray2 = "cArray2, 'D','E','F'"
    //length is now 3, but it holds 'DEF', which is kinda logical but maybe unexpected
    

    You have to explicitly set the length of an array that is filled one member at a time.
    I'm expecting this. I would have liked that it didn't work this way, but I can see how it can cause problems if it's changed (or fixed...) now.


    Richard
  • Joe HebertJoe Hebert Posts: 2,159
    GregG wrote: »
    The way it works currently is the way my code for the past few years has expected it to work.
    I'm confused.. As far as I know it has always worked this way, at least for as long as I can remember

    I’m confused by this thread as well. Length_Array() isn’t broken.

    It’s been functioning the same way since Length_Array(TheBeginningOfTime).

    To the best of my knowledge, there’s nothing to fix.
  • ericmedleyericmedley Posts: 4,177
    Joe Hebert wrote: »
    I’m confused by this thread as well. Length_Array() isn’t broken.

    It’s been functioning the same way since Length_Array(TheBeginningOfTime).

    To the best of my knowledge, there’s nothing to fix.


    It was misbehaving for me with populated variables. That's the part that's broke.
  • ericmedley wrote: »
    It was misbehaving for me with populated variables. That's the part that's broke.

    Could you expand on that a little?

    If you populate the array like:
    cArray[10]
    
    cArray[1] = 'A'
    cArray[2] = 'B'
    etc.
    
    The length of the array will stay at zero. You could argue that it shouldn't, but it has always been this way.

    If you concatenate the array like:
    cArray[10]
    cArray = "cArray, 'A', 'B'"
    
    The length of the array will reflect it's actual length.

    Does the second method doesn't work on a NX controller? That WOULD be bad.


    Richard
  • ericmedleyericmedley Posts: 4,177
    Could you expand on that a little?

    If you populate the array like:
    cArray[10]
    
    cArray[1] = 'A'
    cArray[2] = 'B'
    etc.
    
    The length of the array will stay at zero. You could argue that it shouldn't, but it has always been this way.

    If you concatenate the array like:
    cArray[10]
    cArray = "cArray, 'A', 'B'"
    
    The length of the array will reflect it's actual length.

    Does the second method doesn't work on a NX controller? That WOULD be bad.


    Richard


    It's the latter. I ran a function to populate everything prior to running the send string zero stuff you see in my OP.
  • Jorde_VJorde_V Posts: 393
    ericmedley wrote: »


    It's the latter. I ran a function to populate everything prior to running the send string zero stuff you see in my OP.


    Length_array checks what the values are on compile, not on runtime. So if you populate them in your function it will always return 0 as the length. It works the same in C99 and C++ as well, in C++ you would use vector.size() to get the actual length at runtime. To get the actual length of an array at runtime you could do something like this:
    integer sm_length_array(integer arr[]){
      stack_var count;
      count = 0;
      while(arr[count]) count++;
      return count;
    }
    

    It shouldn't have ever worked the way you describe, due to how the language works (or should if it's supposed to work the same way as C). I'm by no means an expert on the Netlinx language though all I know is that it has always worked that way in C.
  • This just burnt me and it's infuriating...

  • People, Length_Array() is NOT broken. It's working exactly the way it's supposed to. Unlike 'C', which manages array and string lengths differently, there are two functions that provide length information for arrays, and it doesn't matter whether they are in a structure or not.
    Max_Length_Array() and Max_Length_String() both return the number of elements contained in that array or string.
    Length_Array() and Length_String() both return the number of VALID entries in an array. Now the only ways to define how many valid entries are in the array are by:
    1. Defining the elements in the array at the time of array definition.
    2. Dynamically by using Set_Length_Array() or Set_Length_String().

    The functions are setup this way so you can define an array in the main block of code, populate it, and set the number of valid entries. Then, that array can be passed in as an argument to a module. The code in that module has no idea how many elements can be stored in this array, nor does it know how many sequential entries are valid.
    Using the Length_Array() function in the module will report the correct number of valid elements that the array so you know how many items to work with. This becomes a very powerful tool when passing arrays into modules.

    Here's something else to be aware of. Let's say you have an array of integers to store channels for a push event. Now let's say you want to add or remove channels in the array for this event and properly set the array's new length by calling Set_Length_Array(). The event will STILL not operate on those new array channels because the events table is created at program load when those channels weren't in the array. In order for that array to properly kick-off the push event for all new channels, you need to call Rebuild_Event() right after changing the integer array. For example, let's say you had a group of channels in an array associated with a certain category of operations, and at certain times you want to disable the entire group of operations. All you'd have to do is set the channel array length to zero and then call rebuild_event(). When rebuild_event is called, it uses the current length of any array to determine which elements will be entered into the event table.

    DEFINE_VARIABLE
    Volatile Integer chTpConditional[] = {1,2,3,5,7,9,100};

    Define_Function EnableConditional(Char enable)
    {
    If(enable)
    Set_Length_Array(chTpConditional, Max_Length_Array(chTpConditional));
    Else
    Set_Length_Array(chTpConditional, 0);
    Rebuild_Event();
    }

    DEFINE_EVENT
    Button_Event[dvTp, chTpConditional]
    {
    Push:
    {
    do stuff
    }
    }

    I hope this helps you gain a better understanding of arrays in NetLinx.

  • travtrav Posts: 188

    Some pro level thread necromancy.

Sign In or Register to comment.