Length_array borken?
ericmedley
Posts: 4,177
Length_array borken? Did I biff something here? This is on an NX-3200
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
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
0
Comments
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.
i.e. Array1 doesn't have a length, but max_length is 10
Array2 has both set to 10
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
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)
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.
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.
So how would we change it in a way that wouldn't break that code, ie:
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!!!!!!!!!!!!!!!!!!!!
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
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
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.
Could you expand on that a little?
If you populate the array like:
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: 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.
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:
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.
Some pro level thread necromancy.