LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

static int panelHandle cannot be used with extern keyword in another file

Solved!
Go to solution
Hello,
Here is a question I have been thinking to ask since my first application with CVI but I did not ask for I found a "workaround":
CVI code generator automatically defines the panel handle variables as "static int". I like my panel handles to be global variables to be able to use them in multiple files.
However when I tried to use it in another file using the keyword "extern" the compiler gets angry. I can't also write "extern static".
So the only way for me to overcome this problem is to remove the "static" keyword from panel handle definition. I did not see any harm in doing this since my first application. Maybe the answer is very simple but I will be happy if someone can explain the underlying logic.
 
1. Why are the panel handles defined as "static"?
2. Is it a bad programming practice to remove this "static" keyword?
3. How can we use the panel handle outside the file without removing the "static" keyword?
 
Thanks and good luck!
S. Eren BALCI
IMESTEK
0 Kudos
Message 1 of 5
(4,593 Views)
I have done what you described in the past & I haven't had any problems.  I believe the "static" keyword is redundant in C as it is the default storage class for global variables.  Declaring your panelhandle extern will allow it to be seen in external objects.  I guess one other way would be to use shared memory or some other form of interprocess communication to pass a copy of the variable. 
0 Kudos
Message 2 of 5
(4,587 Views)
Solution
Accepted by ebalci
These are really good questions, here is my take.
 
1) maybe someone from NI knows.
 
2) it depends how you feel about global access to variables.   As you have found, the static keyword limits the scope of the panel handle to the current file.  Depending on what rules of programming you follow (this is a little like religion, lots of them) then keeping all access to the panel handle in a single module/file is a good design practice.  By doing this, it makes modification of the program easier later, as changes to the panel affect only a single file.  I  find it much easier to design software that way, particularly when using multiple threads.  But it is personal preference, if you want to remove the static keyword, and access the panel as a global variable, it should not break anything.
 
3) There are a number of ways to do this. 
- You can create functions for each action that must be taken on the panel within the single file that uses the panel uir.  These functions are made public through a header file.  All other files call these functions to access the panel.  This is pretty simple once you have done it a couple of times.   For example
void UpdateCounter(int newCount) {SetCtrlVal(myPanelHandle, PANEL_COUNTER_CONTROL, newCount);}
With this design your display functions are called from your other routines in the other files. 
 
- You can also keep all callbacks and panel access functions in a single file that handles the display.  This file then calls other files to acquire data or take action, but the update of the panel is always made from the callbacks within this file. This is easy to implement if you don't have a very complex user interface.  With this design your display routines call your other functions. 
 
- Yet another method is to create a function to return the panel handle in the file that includes the header for the uir. 
int GetMyPanelHandle(void)  {return(myPanelHandle);}
If you put the declaration for GetMyPanelHandle() in a header you can access it from any file that includes the header.
  SetCtrlVal(GetMyPanelHandle(), PANEL_MY_CONTROL, 0);
Even this simple method can be used to implement thread locking on a panel if needed by adding a release function and a few other  modifications.
 
It is all personal preference, and no one answer fits all situations.
 

Message Edited by mvr on 06-22-2006 09:08 AM

0 Kudos
Message 3 of 5
(4,586 Views)
In C, the static keyword instructs the compiler not to export the variable to the linker, meaning that no other compilation units (c files) can access the declaration.  Declaring a variable "extern" simply means the variable is exported by some other file.  This satisfies the compiler, but the linker is going to complain if that variable was declared static in it's original file.

The main reason I can see for declaring a panel handle static is to allow consistent use of a single variable name (like "panelHandle") throughout your files, even if they all load different panels.  Programmers typically like to stick to conventions, and the code generator likes it even more.  Imagine that you have multiple files that load panels and receive panel handles.  If you declare your panel handles static, you can name them all "panelHandle" without worrying about code from different files interfering with each other.

I don't see any reason you can't remove the static keyword, as long as you are conscious of how you name/use your panel handles.  If you want your handles global, so be it.

Hope this helps.

Mert A.
National Instruments
Message 4 of 5
(4,571 Views)

This explanation of the static keyword is mostly correct. However, the static keyword serves another function and the semantics of its usage is dependent on variable scope.

If the variable is defined as static outside of a function, it behaves as Mert describes.

If it is used within a function, the static keyword indicates to the compiler that the variable is to be allocated on the heap and maintained between function calls as opposed to the normal dynamic allocation of variables on the stack.

There are a number of reasons for choosing one storage class over the other, one of them being stack space limitations. If you define a number of large buffers in a function, it might be better to do so using the static keyword to prevent potential stack overflow. On the other hand, if you are using a function recursively, it will not allocate new variables when using the static keyword making any access to those variables problematic in such a recursive state.

The way to solve the recursion problem is to use malloc (and its variations) to dynamically allocate a buffer in a function. The only problem with this is you need to free the memory before exiting your function to prevent memory leaks.

Isn't programming fun? :Smiley Happy

Martin Fredrickson
Test Engineer

Northrop Grumman
Advanced Systems and Products
San Diego, CA 92128
0 Kudos
Message 5 of 5
(4,562 Views)