External Code in LabVIEW, Part3: How to use the Call Library Node properly to ease multi platform support

This is an old post that has appeared on expressionflow.com on May 19, 2007

Shared libraries are since about LabVIEW 6 the preferred way for use with external code in LabVIEW. While the Call Library Node can directly interface with many existing shared libraries for the platforms LabVIEW supports, they can also be used to interface to shared libraries that were specifically developed for use with LabVIEW. And one of the very neat features of LabVIEW itself is its multi-platform support. This multi-platform support can even be taken to external shared libraries that were specifically developed for use with LabVIEW. If one observes a few rules and makes smart use of some not very well documented facts and features of the Call Library Node, this will result in a very easily maintainable solution both in terms of the C code as well as the LabVIEW VI libraries.

Calling convention

One aspect of shared libraries is, that on some platforms, each function can have different so called calling conventions. A calling convention is a specification how parameters are to be passed to the function. This usually happens over the stack but some not very common calling conventions also can use registers for all or the first x number of parameters. For instance under Windows 3.1 the two most common calling conventions were Pascal and C. The difference between them is that Pascal passes the parameters on the stack from right to left while C passes them in the opposite order. A second difference is that with Pascal the called function is responsible for restoring the stack just before returning to the caller while in C the caller is restoring the stack itself after the function returns. Under Windows 32-bit (9x, ME, NT, 2000, XP) the two most common calling conventions are ’stdcall’ and C. The difference here is only in who is cleaning up the stack as the order of the parameters is really the same in both. In any case having a caller assume a different calling convention than what the called function is implemented in, will always cause a stack corruption and end in the General Protection nirvana, or if implemented in the exception handler, immediately after return of the function to the caller.

While different platforms support different calling conventions, the only common one on all LabVIEW platforms is the C calling convention. This is an important thing to consider when one wants to create multi platform shared libraries. By making sure all exported functions in the shared library use the C calling convention one only needs to maintain one single VI library for all possible LabVIEW platforms.

Library name

Each platform has its own type of naming convention for shared libraries. Under Windows all standard shared libraries use a .dll extension, while under modern Unix systems using ELF shared libraries this is usually the .so extension. Power Macintosh shared libraries normally have a .framework extension.

One handy and not well documented feature in the LabVIEW Call Library Node is the fact that one can simply specify the shared library name as “<name>.*” and LabVIEW will automatically search the directory containing the VI as well as its search paths for a shared library file consisting of the <name> part together with the appropriate extension for the current platform.

So by defining the name of the shared library in all Call Library Nodes as “mylib.*” for instance, you can truly have one single VI library that interfaces on all LabVIEW platforms to the correct shared library. You can even put all those shared libraries into the same directory and LabVIEW will pick the right one. Unfortunately this does not work for Macintosh systems since a shared library there is really a collection of files in a subdirectory and some of these files make use of the resource fork, which gets lost if these files are copied to a non Macintosh file system.

LabVIEW manager function use

A common misconception is that only CINs can make use of the LabVIEW manager functions documented in the External Code Reference Manual. This is absolutely not true. A shared library can just as easily call any exported LabVIEW manager function such as NumericArrayResize() to create LabVIEW compatible data types, which eventually even can be passed back to LabVIEW to be used on the diagram unaltered. To be able to do that, your shared library only needs to include the extcode.h and possibly the hosttype.h file in the cintools directory and link with the labview.lib file in that same directory. The only limitations are that the functionality of those LabVIEW manager functions really is provided by the LabVIEW development environment or runtime system. Therefore a shared library linking to any of those functions will only be executable (in fact loadable) in the LabVIEW development environment or in a LabVIEW executable. But this can hardly be considered a disadvantage, as CINs by nature only can run in those environments.

Use of these LabVIEW manager functions can make your C code a lot more uniform across platforms. These functions are provided by LabVIEW on all platforms in the same way, and are guaranteed to have the same semantics and behaviour. This can greatly reduce the number of places in your source code where you would otherwise have to provide specific code parts for the different platforms or compiler tool chains.

Conclusion

Knowing the details about the previous three sections one can create a single VI library interfacing to the appropriate shared library for the platform, LabVIEW is currently running on. We will see this in one of the upcoming articles in this series.

Leave a Reply

Your email address will not be published. Required fields are marked *