Gathering the necessary information
In order to call a function from a DLL, you need to know four pieces of information:
- The library file in which the code for the function resides
- The name of the function as it appears in the library
- The number and type of arguments the function requires, including the return type
- The calling convention
Items two and three together make the function prototype.
If you are the author of the library, you should already have this information. If the library is from a third party, you should consult the documentation that came with the library to gather this information. (If you are trying to access a function that is part of the Win32 SDK, see the link below.) You may find that you need to look in the header (.h) file included with the DLL in order to find the function prototype. LabVIEW is able to call functions with either C or standard (PASCAL, WINAPI) conventions. Most DLLs use standard calling conventions, and this can usually be assumed, if it is not explicitly stated. If the calling conventions are wrong, LabVIEW will crash when your VI tries to call the function.
When you have the information, it should look something like this:
Library: Function Prototype: Calling Conventions: | mydll.dll void MyFunction(int a, double* b, char* string, unsigned long arraysize, short* dataarray); standard |
Unfortunately, in order to successfully call this function, you need to understand what the function expects. The first problem is that integer data types are not necessarily consistent in size from one platform to another. LabVIEW alleviates this problem by refering to all integers in a consistent manner. To convert from LabVIEW's notation, to the notation of your particular platform, use the following table:
LabVIEW | Win32 | Win16 | Macintosh (PowerPC) | Most UNIX Systems |
int8 | signed char | signed char | signed char | signed char |
int16 | short | int, short | short | short |
int32 | int, long | long | int, long | int, long |
uInt8 | char | char | char | char |
uInt16 | unsigned short | unsigned int, unsigned short | unsigned short | unsigned short |
uInt32 | unsigned int, unsigned long | unsigned long | unsigned int, unsigned long | unsigned int, unsigned long |
Furthermore, you also need to know what the function expects in terms of pointers. Some parameters are passed by value, and some are passed by pointer. For those passed as pointers, the function may expect a single value, or it may expect the starting location of an array of values. Knowing which one is critical if you are to successfully call the library function. In the example above, you can guess from the parameter names, and read in the (hypothetical) manual that dataarray should be a pointer to an array of shorts, while b is a pointer to one double value.
The final piece of information is that strings are generally passed to DLLs as C strings. A C string is an array of chars, and as such, is normally seen in function prototypes as "char*", a pointer to a character array. Incidentally, C functions know when they've reached the end of a string because they are always terminated with a null character (ASCII value 0x00).
With all of this information, you can write a slightly revised function prototype (assuming a Win32 OS):
void MyFunction(int32 a, double* b, char* string, uInt32 arraysize, int16* dataarray);
where:
b is a pointer to one double value,
string is a C String pointer, and
dataarray is a pointer to an array of int16s
Configuring the Call Library Function Node
Once you've gathered all of the necessary information, you are ready to set up the Call Library Function Node. The first thing to do, of course, is to place a node on the block diagram. The Call Library Function Node is found on the
Functions Palette >>
Connectivity >>
Libraries & Executables >>
Call Library Function Node. After placing the node on the diagram, you must configure it. Popup on the node and select
Configure.
This will bring up a dialog that allows you to configure the function call.
On this dialog, enter the path to the desired library, the name of the function, and the calling conventions. Continue configuring the Call Library Function Node based on your application's needs.
Once finished, the node will display the appropriate terminal data type on the block diagram:
If the library file cannot be found, or the function cannot be found within the library, you will get a broken run arrow. Click the broken run arrow to display the error list and find the offending node.
Declaring a function call to a library function threadsafe (reentrant)
If you know that the function you are calling in the library is threadsafe, you may inform LabVIEW by appropriately configuring the node. If the node is not configured as a threadsafe call, the call is assumed to be non-threadsafe, and is run in the User Interface thread. This ensures that two calls are not made simultaneously to a non-threadsafe function. If the function is threadsafe, however, it should be configured as such, as this leads to performance improvements.
To configure a call library function as threadsafe, change the dropdown box that says "Run in UI Thread," to "Reentrant."
Having done this, the top of the node changes from orange to yellow, indicating that the call is reentrant.
UI Thread | | Reentrant |