LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Labview DLL and Defining Static Variables

A Labview DLL that I am making currently consists of three parts:
1) Initialization protocols for a data recorder
2) Data retrieval from digital data recorder
3) Uninitialization of the data recorder
 
The DLL has one large sequence structure broken into three sections, and inside each segment there is a true/false case statement which allows the code to run or not.  Each case statement is run one-at-a-time by sending a "selection" value to the DLL which signifies which of the three case statements should execute.  There are hard coded wires running between each of the three in-line sequence structures enabling data to flow from left to right as the code in the DLL executes.
 
What happens to the state of the data in the hard coded wires when the DLL runs some code in one of the case statements and hands control back to VB?  In other words, in VB I can define variables which are static or self-destruct upon leaving a subroutine.  How is this controlled in Labview?
 
Also, in the "false" case statements, what is the effect of selecting "use default if unwired"?  I would like to explicitely define this connection properly but am not sure how to proceed.  I would the data held in this wire to be the same data that passed during the function call when the case was "true".
 
Thanks.
0 Kudos
Message 1 of 10
(4,593 Views)

I'm having a little difficulty in understanding your architecture. Normally, you would build a dll that contains different function calls. In other words, you would have an init function, a read function, and an uninit function. In the LabVIEW world, you do this by having three separate VIs that you include into the single dll.

A sequence structure is not something that most LabVIEW programs reqlly require in the first place and I think you might have problems with the way you are implementing it and the case statements but I would like to see the code. The default value of an exit tunnel will depend on the data type. For a string, it's an empty string. For a numeric, it's zero. And for a Boolean, it's false. You can of course define any constant you want. the only way that I see that you can have the false case pass the data that was generated in the true case is with an uninitialized shift register but all of that complexity could be avoided if you created 3 separate VIs, eliminated the sequence structure, and had no case statements.

0 Kudos
Message 2 of 10
(4,584 Views)

Hi Dennis,

First of all, thanks for the response.

You mentioned the traditional approach is to make three separate VI's.  Creating three VI's is easy enough to do, but I have data that I want each VI to see data that is generated by the other VI's.  If I have three separate VI's, how do I get the data such that is static (seen) to the others?  In VB I would simply create global variables and update them as needed.  But in Labview's case, I am not sure how to approach this.

A flat sequence structure sounded a lot more logical to me.  Here's how I envision the process:

1) Create a single Labview DLL with one VI

2) Inside the VI there are multiple function calls, each contained in either true/false case structures or an indexed stacked case statement

3) Call each Labview function by sending a index number from VB to the Labview DLL

4) Labview then "selects" the proper function call by using the selector value

5) Labview DLL then returns data in the form of a variable or array, as needed, back to VB

The beauty of this approach, I only have to create one VI and all the function calls are embedded therein.  No need to open mulitple VI's and make changes to the code in each one.

Now my problem is; how do I keep data in the Labview DLL persistent after VB makes a call to the DLL.  If I made a C DLL, which I have done many times, I would simply setup a variable with a DLL wide scope, such that all the function calls in the DLL can see the change to the variable.  This is what I want to in Labview, but am not sure how to go about it.

Thanks, Jim.

0 Kudos
Message 3 of 10
(4,579 Views)

A stacked sequence structure or flat sequence structure is usually used by people who are transitioning from text based languages. In LabVIEW, you use data flow. If you want to use a single case statement, that's fine. To make data persist, as I mentioned, you can use an unitialized shif register. You have a while loop around the entire VI and create a shift register for each variable that you want to maintain. Writing to a global variable shoul also work. You could have case 1 write to global variable z and case 2 read from global variable z. I've never used global variables in a dll but I can't think why it would'nt work. This should be equivalent to your variable with a DLL wide scope.

The beauty of using three different VIs is that each function call returns data wherever you have an indicator and accepts data wherever you have a control. If you call function A and it returns data x. If data x is required by function B, then data x is passed as an input to function B.

0 Kudos
Message 4 of 10
(4,576 Views)

OK, Dennis, I am with you on using a Do...Loop for maintaining variables through the use of shift registers.  I done that on several Labview projects with good success.  However if I create a giant Do...Loop around the code in the Labview DLL, how does the code ever return control back to VB?  Something has to cause a jump out of the Do...Loop to return out of the DLL.  And when jumping out of the Do...Loop back to VB, will the variables maintained by the shift registers be held in a static state, during the change of control back to VB?  Or are they by default, reset, after VB makes another call to the Labview DLL?

Maybe a more appropriate question might be:

If I create the three separate VI's needed to create the Labview DLL in the "classic" Labview programming sense, then how do I get the variables to be seen by each of the separate VI's?  What mechanism is used in Labview to achieve this?  In VB for example a simple DIM statement at the head of the subroutine is all that is needed to make the variable visible to subroutines in that particular module (VI).  Likewise, if I have multiple modules (VI's) and need a system wide variable, then I create an additional separate module that contains only Global variables, thus enabling a program wide scope for their manipulation.  Does Labview, when adding three separate VI's to create a DLL, require the same approach?  I sounds like I need to use Labview globals somewhere in my project.  True?  And if so, where do I put them?

0 Kudos
Message 5 of 10
(4,558 Views)

First of all, it's called a while loop or for loop in LabVIEW. With a while loop, if you wire a false constant to the termination terminal, it will execute once. If you wire a 1 to the count terminal of a for loop, it will execute once. With an unitialized shift register, it will retain it's value as long as the VI is kept in memory. This is the basis of what is called a LabVIEW-2 style global. There have been numerous posts on this subject and is also discussed in the shipping documentation for LabVIEW. As long as your VB code does not remove the dll from memory, this should work that same way.

I guess I don't understand where the confusion is with the three separate VIs and getting variables seen the others. For a simple example, say you have a VI that calculates the sum of 2 numbers so you have two controls and an indicator in this VI. This sum is needed by a second VI so you have a control called 'sum' in this second VI. If made into a dll with two separate function calls, when you call function one, you pass it the two numbers you need to add and it returns the sum. You store the return value in your VB code and when it's time to call the second function, you pass it the value that you've saved. This would be no different than if your VB code calculated some value that you wanted to pass to any other type of dll - not just one created in LabVIEW. I could post a LabVIEW example that calls a dll but I don't know if that would help you any. I don't have VB installed at this time and really don't want to have to do it. Here's a picture of how I would break up the single VI into separate ones.

0 Kudos
Message 6 of 10
(4,552 Views)

OK Dennis!! Your last reply really cleared things up for me.  You are saying that each VI in Labview is treated as a completely separate entity where all the variables are local in scope, only to that VI.  And, the only way to allow multiple VI's to see each others data is by passing parameters during calls to each VI.  I can understand and work with that.

It does seem to be a limitation however when creating a Labview DLL for a rather large project that utilizes 10's or 100's of variables that need to be shared with all the VI's in the DLL.  I have several projects that do indeed contain this many variables.  VB (or C) for example gives much more flexibility in the way these variables can be shared amongst various function modules.  I kept probing in my questioning in hopes that Labview would also offer this flexibility.  It seems the only way to accomplish the task of passing large quantities of variable data is create structures of these variables and pass them back and forth to the various VI's needed for the project.  Of course this means more overhead for the program while running because of this movement in memory.

OK, at least I know now what is expected for utilizing Labview DLL's, and thanks for your kind comments.

0 Kudos
Message 7 of 10
(4,548 Views)

No problem. I'm glad things are a little clearer.

The way I've described is not the only way you could do this of course. I just thought it was the simplest from the brief description you gave. To avoid the complex structures, you could also use global variables. In the example I posted, the first frame of the sequence structure could write to global variable 'A'. The second frame could have a read of global variable 'A'. As long as the dll is kept in memory, the contents of global variable 'A' will persist so the sharing you use in VB and C is also possible. The downside of this method as I see it is that you have to be very careful about the order in which you call the single function and it' more difficult to validate the data stored in the global. If you went this way, you would probably want to add some additional error checking in the LabVIEW program to make that what is written to the global is okay.

0 Kudos
Message 8 of 10
(4,544 Views)
After our disussion above, I was "thinking outside the box" and decided to try a much simpler approach to creating a Labview DLL, which is called by VB.  Being primarily a text based programmer, I wanted to create a Labview DLL project that kept all the function calls in one VI and not have them spread across several VI's, as is the normal practice in Labview coding.  As in text based programming, where multiple function calls can be placed in one module and are easy to read and understand because of their close proximity in the editing compiler, I wanted the same thing from Labview.  This has been accomplished.
 
To do this I created the code shown in Simple-DLL.JPG.  All the code is in one VI and all parameters that are meant to stay static during calls to the DLL are maintained by local variables.  I'm sure shift registers could be made to work here, but code in this routine is only called once every five or ten seconds.  There are only three parameters that are passed during each call to the center routine to get data back from a digital data recorder.  Those parameters are 1) lSelector, 2) lArraySize, and 3) dArray[].  As mentioned earlier, the other parameters are held static by use of the local variables.
 
I like the simplicity of this approach, and maintenance of code is extremely easy.  Much easier that flipping between multiple function call VI's and the VI holding the global variables.  Reading and understanding the code is also easy to do in this approach.
 
Obviously, if one has a project where multiple functions are called with many variables being passed back and forth, then my example may have limitations.  But I wanted to document the above approach for text based programmers to reap the benefits of something easy to understand and implement, especially when their programming experience with Labview is limited, and their Labview project is relatively small.  Your comments are welcome!!
0 Kudos
Message 9 of 10
(4,532 Views)

Well, it makes for ugly LabVIEW code though.Smiley Wink

Local and global variables break the dataflow design of LabVIEW and your design would get poor marks if it was to be used strictly in LabVIEW. Also, every time you use a local, you create a copy. With large arrays, this can pose a problem. When I mentioned globabl variables, I should have mentioned that is preferable to use what is called a LabVIEW-2 style global variable. What this is basically a VI with an unitialized shift register. There's additonal information on these in the shipping documentation but they avoid the data duplication problem and race conditions.

Obviously, I can't see your false case in the first frame but I don't understand the point of writing some constants to the local variables 'Array 3' and 'Last Data Number 2'. If these are constants necessary for frame 2, why don't you just place the constants in frame 2? Since you are initializing the shift register in frame 2 with them, every time frame 2 is called, it will start with the defaults. You are not writing to the local variable when frame 2 finishes.

0 Kudos
Message 10 of 10
(4,525 Views)