Wildcards in the LabVIEW Call Library Node

LabVIEW being a multiplatform development system has a few handy and neat features that allow more easily to write one single VI library to interface to the different types of shared libraries on the the different platforms.

Shared libraries come in various forms depending on the platform they are build for. On Windows they use the well known .dll extension, under Linux and most other Unix versions they have the .so extension and on MacOS X they use the .framework extension for a so called bundle, and .dylib for the binary loadable module. A bundle is in reality a directory with various subdirectories that contain version resource files as well as (potentially) multiple version of the actual binary shared library and that can even consist of different binary shared libraries for multiple architectures. So can a bundle contain both a 32-bit x86 shared library as well as a 64-bit x64 shared library and also an ARM64 shared library. The shared library loader will then automatically reference the correct one, depending on the architecture of the current platform and the calling application. As far as the Graphical Shell of MacOS X is concerned it will not show a bundle as a directory in which one could browse into but instead simply represent it as an object.

But all this is only a MacOS X feature. All other systems on which LabVIEW can run, do not have such an automatic multi architecture bundle system. Linux uses something else called multiarch, which is similar to the way Windows handles the difference between 32-bit and 64-bit binary compiled code. It maintains different directories for each bitness and the shared module loader will search in the according directories that match the bitness of the application requesting to load a certain library. But this only works for shared libraries that are installed in this OS folders. And there still remains the issue that the actual shared library is called mylibrary.dll under Windows, while it should be called mylibrary.so under Linux and mylibrary.framework for MacOS X.

The LabVIEW Call Library Node supports a handy feature for a very long time already. This is present at least as far back as LabVIEW 7. If one enters as library name simply mylibrary.*, LabVIEW will automatically replace the asterix after the dot with the default ending for the platform it is running on. So if you write some shared library that you want to call from LabVIEW, and make sure to keep the function interfaces the same on every platform, you can simply give it on all platforms the same file name with the according file ending and then write one single VI library to call the different functions and use the same VI library on different platforms. Of course since around LabVIEW 8.6 the Call Library Node also allows to pass a path from the diagram, which can be computed at runtime by building the correct library name and passing that to the Call Library Node. This works too, but the use of simply one single name in the Call Library Node itself is potentially much easier to maintain (as long as you don’t decide to change the name of the shared library later on for some reason).

Platform EndingExampleResult
Windows.dllmyLibrary.* myLibrary.dll
Linux.somyLibrary.* myLibrary.so
MacOS X.frameworkmyLibrary.* myLibrary.framework
Pharlap.dllmyLibrary.* myLibrary.dll
VxWorks.outmyLibrary.* myLibrary.out
NI Linux RT.somyLibrary.* myLibrary.so
The ending LabVEW will use on the different platforms instead of the asterix

Different shared libraries for 32-bit and 64-bit

With LabVIEW 2009, LabVIEW for Windows was the first version to also run as 64-bit application. But that gives some extra problems. While Microsoft did add some support for loading 16-bit DLLs into a 32-bit process, they never got very happy with that. It was cumbersome to use, very hard to get right and very difficult to support properly. They were careful to avoid these problems this time, by simply not letting a 64-bit process load a 32-bit DLL. With some serious assembly code it would be of course possible. But who in his right mind wants to do assembly programming nowaday? Microsoft simply said, no it can’t be done and that was it. There was some initial complaining of people who wanted to take shortcuts by not having to compile their shared libraries for 64-bit and push the burden on the users of their shared library, but pretty soon everybody had accepted that it simply can’t be done and started the process of recompiling and often rewriting their software for 64-bit. Only cleanly developed and written code was easy to port, and many who had thought they had been very careful and only written absolutely clean code, discovered now that their code wasn’t quite as clean and actually contained many assumptions that only worked for 32-bit compilation.

But how can a LabVIEW VI be written, so that it can call the correct shared library no matter if the VI is executed in the 32-bit or 64-bit version of LabVIEW? We don’t necessarily want to have to resort to the Conditional Compile structure to place two or more almost identical Call Library Nodes in every VI that wants to call a shared library. If the shared library is installed in the system, the OS takes care about that by maintaining different directories for the two architectures and loading only from the one that applies to the process demanding to load a shared library. But if that shared library is application private, for instance alongside the VIs that call it, things are not so simple. The OS doesn’t know which directory would be for which architecture, if there are even separated directories.

The LabVIEW developers chose to extend the earlier used wildcard system a little more. This is actually also documented in the online help to the Call Library Node since around LabVIEW 2011 or so, but who is reading manuals anyways? 🙂

If the library name contains an asterix before the point indicating the start of the file ending, this asterix is replaced by LabVIEW with the number “32” if it is running in LabVIEW 32-bit and with “64” if it is running in LabVIEW 64-bit and the resulting name is used to try to load the shared library. If there are two consequent asterix’ in the filename, LabVIEW will replace them with an empty string in LabVIEW 32-bit and with “_64” in LabVIEW 64-bit.

Filenameresulting 32-bit filenameresulting 64-bit filename
myLibrary*.dllmyLibrary32.dllmyLibrary64.dll
myLibrary**.dllmyLibrary.dll myLibrary_64.dll
my*Library.dllmy32Library.dll my64Library.dll
my**Library.dllmyLibrary.dll my_64Library.dll
Examples of wildcard filenames and their resolution depending on the LabVIEW platform

With these little tricks it is fairly easy to write LabVIEW VI libraries that do not need Conditional Compile structures or other platform specific wizardry in the diagram and can still call external shared libraries on different platform without requiring any changes to the VI code.

LabVIEW 2014 added support for 64-bit applications to Linux and MacOS X versions and uses the same wildcard technique on these platforms too. LabVIEW 2016 was the last version on Linux and MacOS X to be possible to install as 32-bit version. On Linux and MacOS X, LabVIEW is 64-bit only since 2017. While it may still be available as 32-bit version on Windows for maybe one or two more years, this is ultimately going to be discontinued at some point too, and I would expect this to be not in a far future.

Leave a Reply

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