Using LabVIEW Manager Functions in Shared Libraries

LabVIEW has a suite of functions that you can call from shared libraries. This suite of functions performs user-specified routines using the appropriate instructions for a given platform. These routines, which manage the functions of a specific operating system, are grouped into the following categories:

Portability of LabVIEW Manager Functions

External code written using the LabVIEW managers is portable, that is, you can compile it without modification on any platform that supports LabVIEW. This portability has the following advantages:

Note��When you call the LabVIEW manager functions from a shared library, use #include extcode.h in any files that use manager functions and link to labviewv.lib. Set the structure alignment of the compiler to 1 byte.

To achieve platform independence, data types should not depend on the peculiarities of various compilers. For example, the C language does not define the size of an integer. Without an explicit definition of the size of each data type, you have difficulty creating code that works identically across multiple compilers. LabVIEW managers use data types that explicitly indicate the size of the data type. For example, if a routine requires a 4-byte integer as a parameter, you define the parameter as an int32. The managers define data types in terms of the fundamental data types for each compiler. Thus, on one compiler, the managers might define an int32 as an int, while on another compiler, the managers might define an int32 as a long int. When you write external code, use the manager data types instead of the host computer data types so your code is more portable and has fewer errors.

Pointers as Parameters

Some manager functions have a parameter that is a pointer. These parameter type descriptions are identified by a trailing asterisk, such as the ph parameter of the DSCopyHandle allocating and releasing function, or are type defined as such, such as the name parameter of the FNamePtr function. In most cases, the manager function writes a value to pre-allocated memory. In some cases, such as FStrFitsPath or GetALong, the function reads a value from the memory location, so you do not have to pre-allocate memory for a return value.

The following functions have parameters that return a value for which you must pre-allocate memory.

DSMemStats FNamePtr
DSCopyHandle FNewRefNum
DateToSecs FPathToArr
DSMemStats FPathToAZString
FCreate FPathToDSString
FCreateAlways FPathToPath
FFlattenPath FRefNumToFD
FGetAccessRights FStringToPath
FGetEOF FTextToPath
FGetInfo FUnflattenPath
FGetPathType GetAlong
FMOpen SetALong
FMRead RandomGen
FMTell SecsToDate
FMWrite NumericArrayResize

You must allocate space for this return value. The following examples illustrate incorrect and correct ways to call one of these functions from within a generic function foo.

Incorrect example:

foo(Path path) {

����PStr p;/* an uninitialized pointer */ File *fd;/* an uninitialized pointer */

����MgErr err;

����err = FNamePtr(path, p);

����err = FMOpen(fd, path, openReadOnly denyWriteOnly);

����}

In the incorrect example, p is a pointer to a Pascal string, but the pointer is not initialized to point to any allocated buffer. FNamePtr expects its caller to pass a pointer to an allocated space and writes the name of the file referred to by path into that space. Even if the pointer does not point to a valid place, FNamePtr writes its results there, with unpredictable consequences. Similarly, FMOpen writes its results to the space to which fd points, which is not a valid place because fd is uninitialized.

Correct example:

foo(Path path) {

����Str255 buf; /* allocated buffer of 256 chars */

����File fd;

����MgErr err;

����err = FNamePtr(path, buf);

����err = FMOpen(&fd, path, openReadOnly, denyWriteOnly);

����}

In the correct example, buf contains space for the maximum-sized Pascal string, whose address is passed to FNamePtr. fd is a local variable (allocated space) for a file descriptor.