According to my understanding and the following discussion:
certain types of Property nodes and Invoke nodes should be inlineable without any great problems.
I would suggest that the LabVIEW compiler get's a bit smarter about this aspect of limiting the ability to inline code. If there's no technical limitation regarding inlining of a property node or Invoke node which is fed with a reference (which does not originate from a local object i.e. a static reference to a FP object) then it should be inlineable.
I was searching for occurences of a reference to a Graph in one VI, and as I was interrupted, came back to the search result after the interruption, only to discover that the Search Result Window did actually not show ANY kind of useful information regarding the object I was searching references for:
I know I have outrageous expectations as a LabVIEW user, but this seems to me an odd lack of feature:
- From this window, I have absolutely no clue what I am searching for. In particular, if I have in the mean time jumped from windows to windows...
- ...there is no way to go back to the object these references are linked to (unless I go to one of the references and then look for the Control or Indicator they are associated with).
Of course asking for a VI information when this is provided in the list below is maybe unnecessary.
But consider this global variable whose references I was looking for:
Same thing here:
- I do not know the type of the global.
- I do not know which VI it is part of (Globals are saved in a VI).
- I do not know where I started my seach from (but that's more of a back-to-source button issue).
Suggestion: provide as much information as possible about the starting point of the search, when said starting point is an object (by contrast to a text search).
Tested in LV 2013 SP1 64 bits.
There is a construct I am quite fond of in pointer-friendly languages, using iterator math to implement circular buffers of arbitrary data types. They are a little bit slower to use than straight arrays, but they provide a nice syntax for fixed sized buffers and are helpful in cases where you will be prepending and appending elements.
I am pretty certain that queues are implemented as circular buffers under the hood, so much of the infrastructure is already in place, this is mostly adding a new API. Added bonus: the explicit circular buffer can be synchronous, unlike the queue, so for example you can put them in subroutine VIs.
It should be easy to convert 1D arrays to/from circular buffers. Array->CB is basically free, the elements are in order in memory. CB->Array requires two block copies (most of the time). This can be strategically mananged, much like Reverse or Transpose operations.
You can implement most of the following two ideas naturally:
Circular buffers would auto-index and cycle the elements and not participate in setting 'N'.
You can do 95+% of what I wanted to do with negative indexing:
A lot of the classic divide and conquer algorithms become tractable in LV. You can already use queues to implement your own stack and outperform native recursion. A CB implementation of the stack would be amenable to subroutine priority and give a nice performance kick. I have done it by hand for a few datatypes and the beauty and simplicity of the recursive solution gets buried in the implementation of the stack. A drop-in node or two would give you a cleaner look and high-octane performance.
Finally, perhaps the most practical reason yet: simple XY Charts.
As for appearance I'd suggest a modified wire like the matrix data type. Most if not all Array primitives should probably accept the CB. A few new nodes are needed to get/set buffer size and number of elements and to do the conversions to/from 1D arrays. The control/indicator could have some superpowers: set the first element, wraparound scrolling (the first element should be highlighted).
I think the Array Element Gap should be sizable. This would facilitate lining up FP arrays with other items on the FP, or simply as a mechanism to add more apparent delineation between elements.
The size should be set in the Properties box, not by dragging the element gap with the mouse - that would add too much "cursor noise".
A new Property Node for this feature would complete Idea.
Currently, you can place a probe on a wire while developing, which is an indicator of the data on a wire. I want the ability to CONTROL the data on the wire, with a data forcing mechanism.
The implementation would be very simple... right click on a wire, and in the context menu the option "Force" would be right under "Probe." It would pop up a window of the forcing control, and while the VI is running and forcing is set to "Enable", the programmer can control the values that pass on the wire. If the force window were set to "Disable", the data in the wire would be completely controlled by the VI's logic.
I think the implementation by NI could be trivially simple. If you only allow a forcing control to be added during edit mode (not while the VI is running), the force could be added as an inline VI (as denoted by the green rectangle on the wire). The code inside the inline VI would be as follows, and the front panel would be "Data Force (1)" as shown above.
Of course, if you could add a force to a wire during runtime like probes, props NI. But I would be PERFECTLY happy if you could only add these force controls in edit mode prior to running.
One level further (and this would be AMAZING, NI, AMAZING): enable and disable certain parts of the cluster that you would like to force and allow the other elements to be controlled by the VI logic. I made the example above because it would be very natural to ONLY force Sensor1 and Sensor2, and letting the output run it's course from your forced input.
The BeagleBoard xM is a 32 bit ARM based microcontroller board that is very popular. It would be great if we could programme it in LabVIEW. This product could leverage off the already available LabVIEW Embedded for ARM and the LabVIEW Microcontroller SDK (or other methods of getting LabVIEW to run on it).
The BeagleBoard xM is $149 and is open hardware. The BeagleBoard xM uses an ARM Cortex A8 running at 1,000 MHz resulting in 2,000 MIPS of performance. By way of comparison, the current LabVIEW Embedded for ARM Tier 1 (out-of-the-box experience) boards have only 60 MIPS of processing power. So, about 33 times the processing power!
Wouldn’t it be great to programme the BeagleBoard xM in LabVIEW?
This should work!! I know there are workarounds and I have used them but it would be much easier.
On Windows, you can define environment variables that auto expand to known directories. There are some variables that are already defined by the system. For example, %TEMP% automatically expands to c:\Users\<username>\AppData\Local\Temp OR WHEREVER THE USER MOVED TEMP DURING INSTALLATION. That's the important part .That makes it possible to write %TEMP%\abc as a symbolic path that works regardless of how the system gets reconfigured.
Users can define their own environment variables, and those get expanded when used in a path in the command line or Windows Explorer (the text entry region at the top of an Explorer window). On Linux and Mac, it is the equivalent of using $VARIABLENAME/abc, where VARIABLENAME is some user-chosen name.
[admin edit] Added background information on environment variables, and updated title to use the word "Environment" instead of "Environmental".
It is common, in writing reusable code, to handle arbitrary clusters in variants. To access the elements of the cluster, one wants to convert the cluster into an array of variants containing the individual items. After access, one needs to convert the array of variants back into the original cluster.
There are several examples of packages that use this on NI.com and in the LAVAg.org Code Repository. They mostly use functions for working with Variant Clusters from OpenG; however, these can be quite slow. Recent LabVIEW versions have had the ability to do much of the functions quicker, however, there is a very imortant missing native ability: to convert an Array of Variants into a Variant Cluster.
The other direction, Cluster to Array of Variants, works like this:
But trying to reverse the process breaks:
So my idea is make the second image work; make an Array of Variants interchangable with a Variant Cluster in the "Variant to Data" LabVIEW primative. The interchangability should apply to contained subclusters/arrays also. The matching of array to cluster elements can be by cluster order rather than element name.
This would greatly aid the performance of reuasable packages that operate on arbitrary clusters.
The shortcut menu should launch the new type def.'s front panel when 'Make Type Def.' is selected. You will need to save it anyway, and if you find the need to edit it right away, then it is already open and ready to go.
Format into text is very useful but can become hard to edit when it has a lot of inputs. I propose, instead of one huge format string, that the programmer be allowed to put the required format next to the corresponding input. Also, the user should be allowed to enter constant strings, e.g.. \n, \t, or "Comment", and have the corresponding input field automatically grayed out.
LabVIEW has a somewhat hidden feature built into the variant attributes functionality that easily allows the implementation of high performance associative arrays. As discussed elsewhere, it is implemented as a red-black tree.
I wonder if this functionality could be exposed with a more intuitive set of tools that does not require dummy variants and somewhat obscure VIs hidden deeply in the variant palette (who would ever look there!).
Also, the key is currently restricted to strings (Of course we can flatten anything to strings to make a "name" for a more generalized use of all this).
I imagine a set of associative array tools:
This is written as both an Idea and as a Community Nugget.
Did you know there exists a function that decreases code fragility when it comes to typecasting and type converting datatypes? It's called 'Coerce to Type', and I bet you've never heard of this function unless you have kept up with this conversation. Thanks to RandyP for creating that Idea which culminated in a 'public' release of the Coerce to Type function.
Since that post, I have become aware of potential risks/bugs I had been proliferating in my coding style. First, I will briefly describe my understanding of the difference between typecasting and typeconverting in the context of LabVIEW. Next, I'll show a few use cases where this node increases code robustness. Finally, it's up to you to Kudos this Idea so we get Coerce to Type officially supported and in the palette!
Simply, "type converting" preserves the value of a wire, and "typecasting" preserves the raw bits that express that value on a wire. These two concepts are not interchangeable - they perform distinctly different data transfer functions (which is why they show up on two separate subpalettes: "Numeric>>Conversion" and "Numeric>>Data Manipulation"). Then there's this new function: Coerce to Type. I think of it as a Coerce-Cast combo. The data input is first Coerced to the datatype harvested from the top input, and then it is typecasted to that type.
Dynamic event registration is sensitive to the name on the wire, and for documentation's sake it has historically been important to typecast the event source ref to achieve a good name. Well, typecasting refs can get you into trouble (ask Ben), especially if you change the source control type while forgetting to update your "pretty name" ref constant.
My next favorite example is when you need to coerce a numeric datatype into an enum. Sometimes it's impossible to control the source datatype of an integer, while it's desirable to typecast the value into an enum for self-documented syntax inside your app.
For instance, take the "standard" integer datatype in LabVIEW - I32 - and cast it to an enum. You're going to get some unexpected results (assuming, you expected the *value* to be preserved). Consider the following scenario:
We have developed an external DLL that is called from LabVIEW using CLFN. I have noticed a weird behavior regarding DLL detaching (unloading).
I have 2 VIs calling the DLL. I run them and then close all of them. In this case, the DLL is detached when the last VI is closed.
However, if I create project containing the same VIs as in scenario 1, when I close all the VIs after running them, the DLL stays loaded until I close the project.
This behaviour does not seem correct. I think LabVIEW should behave the same in both cases.
What do you think?
[admin edit: I changed the idea title per user request. The original title was "DLL shouldn't stay loaded when all the VIs calling it are closed".
Didn't find this idea posted, I think it's a must.
It would be very usefull for MulticolumnListbox Item Names in which we need to change cell values...
I saw in the Forums,Developer are spending more time on the convertion of the programs from UP to Down or Down to UP due to their requirment.
if NI provides the add on tool for Converting Up/Down,Down/Up.
it is easy to use and they can spend more time on other part of Developmnet.
Well, this idea has haunted me for a couple of years, and now I think it's time to break it. I feel the For-loop, the While-loop, and the Timed loop are so similar that they are begging for a merger. It would simplify, and with a little thought strengthen, the API, to have a single configurable Loop Structure instead. What's the difference between a While-loop and a For-loop with a conditional terminal anyway? Have you ever wished for iteration timing information being available inside your For-loop (I know I have)? "Oh but those structures have been around forever, we can't touch those"... Well, what happened with the stacked sequence structure? Please read on for a minute or two and tell me if I'm losing my marbles here. And please chip in with your own modifiers, since LabVIEW is growing in (sometimes unnecessary) complexity. Thus:
Instead I propose the Loop Structure which when initially drawn looks like this:
The above is basically a loop running forever (don't worry, you can stop it), but it can be modified to do many many other things, just be patient . One feature of the loop structure is the box in the upper left corner, which is quite similar to what we have in a For-loop today. This will, no matter the configuration of the loop structure, always show the current iteration setting of the structure. By default that is never-ending, but if you drag in a conditinal terminal you change the loop behavior to a While-loop (note that I suggest a simpler way to get to the terminal than via the right-click context menu):
Arrays can be wired to the structure border as usual to give a For-loop like behavior. The count terminal changes from "Inf" to an "N" to indicate that it's a finite albeit at edit-time unknown number of iterations:
You can wire out of the count terminal inside the loop structure as usual to get the count at run-time of course. If the iteration count can be deducted at edit-time a number will appear instead of the "N":
This number is blue to indicate that it is automatically calculated. You can just type in a new number if you wish to run a different number of iterations, in which case all the usual ideas on this Idea Exchange about what should happen to auto-indexed tunnels apply. If you override the count manually the number will be in black text:
You can of course combine different exit conditions, in this case a fixed number of iterations with a conditional terminal wired as well for possible early exit:
The automatically calculated count terminal aids in determining if the loop actually runs the desired number of times:
All the usual stuff about tunnels, shift registers and so on apply to this structure as well, but on top of that it can also be configured as you're only used to within a timed loop. Consider how valuable some of these parameters and settings could be for ordinary loops, for error handling and for timing for instance. But the main feat is that this is still the same loop structure - it will simplify the palette a lot:
And now an additional feature that ties some of the parameters from the timed structure together with ordinary loops: this loop structure is event-enabled! I propose stuff like this (we're only scratching the surface with this image):
It's late where I am now, so I'll stop now, but all of the above makes it extremely easy to do things you simply can't do today - what about a Priority Structure?:
So, is it time to consolidate the ever-evolving loop code of LabVIEW into one structure to rule them all?
I would like to be able to create executables that don’t require the runtime engine in LabVIEW. Perhaps a palette of basic functions that can compiled without the runtime engine and an option in the application builder for that. I routinely get executables from programmers that don’t require a runtime installation. I just put it on my desktop and it runs. It would be nice that if I get a request, I could create, build, and send them an exe in an email without worrying about runtime engine versions, transferring large installer files to them, etc.
I often have code in my apps where some error-out nodes are not wired, simply because the errors are generally not of interest to me or the error wiring would clutter up my block diagram. Typically this happens a lot in UI handling code where a lot of property nodes are used. For these parts I would rely on the automatic error handling for debugging purposes. One of the drawbacks of this method is that program execution is suspended when the automatic error handler kicks in. Even worse if this happens for code that is in a loop. You're only option then would be to abort the app, which e.g. is no good for your reference-based objects, etc.
I would love to have the ability to just specify my own 'Automatic Error Handler', enabling me to decide what to do with the unhandled errors. Just logging them is what first comes to mind, but maybe also do some special stuff depending on the type of error, just like a 'normal' error handler. I want to be in control!
Added values of this is that your application then has a catch-all error handler which enables you to at least log every error that occurs, even if not wired through. (Everyone forgets to wire some error-out that they actually did want to wire one time or another don't they? ;-))
Ofcourse the proposed setting in the image would ideally also be available programmatically by application property nodes.