The media on which you receive National Instruments software are warranted not to fail to execute programming
instructions, due to defects in materials and workmanship, for a period of 90 days from date of shipment, as evidenced
by receipts or other documentation. National Instruments will, at its option, repair or replace software media that do not
execute programming instructions if National Instruments receives notice of such defects during the warranty period.
National Instruments does not warrant that the operation of the software shall be uninterrupted or error free.
A Return Material Authorization (RMA) number must be obtained from the factory and clearly marked on the outside
of the package before any equipment will be accept ed for warranty work. National Instru ments will pay the shippi ng costs
of returning to the owner parts which are covered by warranty.
National Instruments believes that the informatio n in this manual is accurate. The docume nt has been ca refully review ed
for technical accurac y. In th e even t that te ch nical o r typograp hic al errors exis t, Nation al Inst ruments rese rves th e right to
make changes to subsequent editions of this document without prior notice to holders of this edition. The reader should
consult National Instruments if errors are suspected. In no event shall National Instruments be liable for any damages
arising out of or related to this document or the information contained in it.
XCEPT AS SPECIFIED HEREIN
E
ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
BY FAULT OR NEGLIGENCE ON THE PART OF NATIONAL INSTRUMENTS SHALL BE LIMITED TO THE AMOUNT THERETOFORE PAID BY THE
CUSTOME R
OR INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF ADVISED OF THE POSSIBILITY THEREOF
National Instruments will apply regardless of the form of action, whether in contract or tort, including negligence.
Any action against National Instruments must be brought within one year after the cause of action accrues. National
Instruments shall not be liable for any delay in performance due to causes beyond its reasonable control. The warranty
provided herein does not cover damages, defects, malfunctions, or service failures caused by owner’s failure to follow
the National Instruments installation, operation, or maintenance instructions; owner’s modification of the product;
owner’s abuse, misuse, or negligent acts; and power failure or surges, fire, flood, accident, actions of third parties, or
other events outside reasonable control.
ATIONAL INSTRUMENTS WILL NOT BE LIABLE FOR DAMAGES RESULTING FROM LOSS OF DATA, PROFITS, USE OF PRODUCTS
. N
ATIONAL INSTRUMENTS MAKES NO WARRANTIES, EXPRESS OR IMPLIED, AND SPECIFICALLY DISCLAIMS
, N
Copyright
Under the copyright laws, this publication may not be reproduced or transmitted in any form, electronic or mechanical,
including photocopyi ng, recordi ng, st oring in an info rmation ret riev al syste m, or translating , in whole or in part, wit hout
the prior written consent of National Instruments Corporation.
USTOMER’S RIGHT TO RECOVER DAMAGES CAUSED
. C
. This limitation of the liability of
,
Trademarks
CVI™, National Instruments™, the National Instruments logo, natinst.com™, and The Software is the Instrument™are
trademarks of National Instruments Corporation.
Product and company names listed are trademarks or trade names of their respective companies.
WARNING REGARDING MEDICAL AND CLINICAL USE OF NATIONAL INSTRUMENTS PRODUCTS
National Instruments products are not designed with components and testing intended to ensure a level of reliability
suitable for use in treatment and diagnosis of humans. Applications of National Instruments products involving medical
or clinical treatment can create a potential for accidental injury caused by product failure, or by errors on the part of the
user or application des igner. Any us e or ap plica tion of Na tiona l Instrum ents pr oducts for or inv olving m edi cal or clin ica l
treatment must be performed by properly trai ned and qualifi ed medic al pe rsonne l, and al l tra ditiona l medic al safegu ards,
equipment, and procedu res that are appropriate in the particula r situation to prevent serious injury or dea th should al ways
continue to be used when Natio nal Instrume nts products are being use d. National In struments prod ucts are N OT intended
to be a substitute for any form of establis hed process, procedure, or e quipment us ed to monit or or safeguard human heal th
and safety in medical or clinical treatment.
Contents
About This Manual
Organization of This Manual................................................ ...... ..... ................................xiii
Conventions Used in This Manual...................................................................................xiv
Related Documentation.....................................................................................xv
The LabWindows/CVI Programmer Reference Manual contains
information to help you develop programs in LabWindows/CVI. The
LabWindows/CVI Programmer Reference Manual is intended for use by
LabWindows users who have already completed the Getting Started with LabWindows/CVI tutorial. To use this manual effectively, you should be
familiar with Getting Started with LabW i ndows/CVI, the LabW indows/CVI User Manual, DOS, Windows, and the C programming language.
Organization of This Manual
The LabWindows/CVI Programmer Reference Manual is organized as
follows:
compiler specifics, C language extensions, 32-bit compiler issues,
debugging levels, and user protection.
•Chapter 2, Using Loadable Compiled Modules, describes the
advantages and disadv antages of using compiled code modules in your
application. It also describes the kinds of compiled modules available
in LabWindows/CVI and includes programming guidelines for
modules you generate with external compilers.
•Chapter 3, Windows 95/NT Compiler/Linker Issues, describes the
different kinds of compiled modules available under
LabWindows/CVI for Wi nd ows 95/NT and includes programming
guidelines for modules you generate with external compilers.
•Chapter 4, Windows 3.1 Compiler/Linker Issues, describes the
different kinds of compiled modules available under
LabWindows/CVI for Windows 3.1 and includes programming
guidelines for modules you generate with external compilers.
•Chapter 5, UNIX Compiler/Linker Issues, describes the kinds of
compiled modules available under LabWindows/CVI for UNIX and
includes programming guidelines for modules you generate with
external compilers.
•Chapter 6, Buildin g Multiplatform Applications, contains guidelines
and caveats for writing platform-independent LabWindows/CVI
applications. LabWindows/CVI currently runs under Windows 3.1
and Windows 95/NT for the PC, and Solaris 1 and Solaris 2 for the
SPARCstation.
National Instruments CorporationxiiiLabWindows/CVI Programmer Reference Manual
About This Manual
• Chapter7, Creating and Distributing Standalone Executables and
DLLs, describes how the LabWindows/CVI Run-time Engine, DLLs,
externally compiled modules, and other files interact with your
executable file. This chapter also describes how to perform error
checking in a standalone executable program. You can create
executable programs from any project that runs in the
LabWindows/CVI environment.
• Chapter8, Distributing Li braries andFuncti on Panels, describes how
to distribute libraries, add libraries to a user’s Library menu, and
specify library dependencies.
• Chapter9, Checking for Errors in LabWindows/CVI, describes
LabWindows/CVI error checking and how LabWindows/CVI reports
errors in LabWindows/CVI libraries and compiled external modules.
•AppendixA, Errors and Warnings, contains an alphabetized list of
compiler warnings, compiler errors, link errors, DLL loading errors,
and external module loading errors generated by LabWindows/CVI.
•AppendixB, Customer Communication, contains forms to help you
gather the information necessary to help us solve your technical
problems and a form you can use to comment on the product
documentation.
•The Glossary contains an alphabetical list of terms used in this manual
and a description of each.
•TheIndex contains an alphabetical list of key terms and topics used in
this manual, including the page where each one can be found.
Conventions Used in This Manual
The following conventions are used in this manual.
<> Angle brackets enclose the name of a key on the keyboard—for example,
<Shift>.
- A hyphen between two or more key names enclosed in angle brackets
denotes that you should simult aneously press the na med keys—for
example, <Ctrl-Alt-Delete>.
» The » symbol leads you through nest ed menu items and dial og box options
to a final action. The sequence File»Page Setup»Options» Substitute Fonts directs you to pull down the File menu, select the PageSetup item,
select Options, and finally select the Substitute Fonts options from the
last dialog box.
This icon to the left of bold italicized text denotes a note, which alerts you
to important information.
!
boldBold text denotes the names of menus, menu items, parameters, or dialog
bold italicBold italic text denotes an activity objective, note, caution, or warning.
italicItalic text denotes variables, emphasis, a cross reference, or an introduction
monospaceText in this font denotes text or characters that you should literally enter
monospace boldBold text in this font denotes the messages and responses that the computer
monospace italic
pathsPaths in this manual are denoted using backslashes (\) to separate drive
This icon to the left of bold italicized text denotes a caution, which advises
you of precautions to take to avoid injury, data loss, or a system crash.
box buttons.
to a key concept. This font also denotes text from which you supply the
appropriate word or value.
from the keyboard, sections of code, programming examples, and syntax
examples. This font is also used for the proper n ames of disk d ri ves, p aths,
directories, programs, functions, filenames and extensions, and for
statements and comments taken from programs.
automatically prints to the screen.
Italic text in this font denotes that you must enter the appropriate words or
values in the place of these items.
names, director i es, fol ders, and files .
Related Documentation
You may find the following documentation helpful while programming in
LabWindows/CVI:
•Microsoft Developer Network CD, Microsoft Corporation,
Redmond WA
•Programmer’s Guide to Microsoft Windows 95, Microsoft Press,
Redmond WA, 1995
•Harbison, Samuel P. and Guy L. Steele, Jr., C: A Reference Manual,
Englewood Cliffs, NJ: Prentice-Hall, Inc., 1995
National Instruments CorporationxvLabWindows/CVI Programmer Reference Manual
About This Manual
Customer Communication
National Instruments wants to recei v e you r comments on our p roducts and
manuals. We are interested in the applications you develop with our
products, and we want to help you if you have problems with the m. To
make it easy for you to contact us, this manual contains comment and
technical support forms for you to complete. These forms are in
Appendix B, Customer Communication, at the end of this manual.
This section describes specific LabWindows/CVI compiler limits, options, defines, and
diversions from the ANSI C standar d.
1
Compiler Limits
Table 1-1 shows the compiler limits for LabWindows/CVI.
Table 1-1.
Coding AttributeLimit
Maximum nesting of #include32
Maximum nesting of #if, #ifdef16
Maximum number of macro parameters32
Maximum number of function parameters64
Maximum nesting of compound blocks32
Maximum size of array/struct types2
National Instruments Corporation1-1LabWindows/CVI Programmer Reference Manual
LabWindows/CVI Compiler Limits
31
Chapter 1LabWindows/CVI Compiler
Compiler Options
Y ou can set the LabW indows/CVI compiler options by selecting Options»Compiler Opti ons
in the Project window. This command opens a dialog box that allows you to set
LabWindows/CVI compiler options. For a discussion of these options, refer to the Compiler Options section in Chapter 3, Project Window, of the LabWindows/CVI User Manual.
Compiler Defines
The LabWindows/CVI compiler accepts compiler defines through the Compiler Defines
command in the Options menu of the Project window. For more information, refer to the
Compiler Defines section in Chapter 3, Project Window, of the LabWindows/CVI User
Manual.
C Language Non-Conformance
LabWindows/CVI for UNIX does not allow you to pass a struct as one of a series of
unspecified variable arguments. Because of this,
LabWindows/CVI if
type is a struct type.
va_arg (ap, type) is not legal in
LabWindows/CVI accepts the
#line preprocessor directive, but ignores it.
C Language Extensions
The LabWindows/CVI compiler has several extensions to the C language. The purpose is to
make the LabWindows/CVI compiler compatible with the commonly used C extensions in
external compilers under Windows 95/NT.
Keywords That Are Not ANSI C Standard
LabWindows/CVI f or Windo ws 3.1 accepts the non-ANSI C keywords pascal, PASCAL, and
_pascal, but ignores them.
Calling Conventions (Windows 95/NT Only)
You can use the following calling convention qualifiers in function declarations:
cdecl
_cdecl
__cdecl
_stdcall
__stdcall
In Microsoft Visual C/C++, Borland C/C++, and Symantec C/C++, the calling convention
normally defaults to __
(recommended)
(recommended)
cdecl if you do not use a calling convention qualifier. You can,
however, set options to cause the calling convention to default to __stdcall. The behavior
is the same in LabWindows/CVI. Y ou can set the default calling conv ention to either __
__stdcall using the Compiler Options command in the Options menu of the Project
or
window. When you create a new project, the default calling convention is
__cdecl.
cdecl
In Watcom C/C++, the default calling convention is not __
-4s (80486 Stack-Based Calling) op tio n when you compil e a module in Watcom for
use the
cdecl or __stdcall. You must
use in LabWindows/CVI. Refer to the Compatibility with External Compilers section in
Chapter 3, Windows 95/NT Compiler/Linker Issues. The
-4s option causes the stack-based
calling convention to be the default. In LabWindows/CVI under W atcom compatibility mode,
the default calling con vention is always the stack-based con vention. It cannot be chan ged. The
LabWindows/CVI compiler accepts the
Watcom, except that floating point and structure return values do not work in the
calling convention. National Instruments recommends that you avoid using
__cdecl and __stdcall conventions under
__cdecl
__cdecl with
Watcom.
__cdecl calling convention and the Watcom stack-based calling convention, the
In the
calling function is responsible for cleaning up the stack. Functions can have a variable number
of arguments.
__stdcall calling convention, the called function is responsible for cleaning up the
In the
stack. Functions with a variable number of arguments do not work in
__stdcall qualifier on a function with a variable number of arguments,
the
__stdcall. If you use
LabWindows/CVI does not honor the qualifier. All compilers pass parameters and return
values in the same way for
__stdcall functions, except for floating point and structure
return values.
National Instruments recommends the
__stdcall calling convention for all functions
exported from a DLL, except functions with a variable number of arguments. Visual Basic
and other non-C Windows programs expect DLL functions to be
__stdcall.
Import and Export Qualifiers
You can use the following qualifiers in variable and function declarations:
National Instruments Corporation1-3LabWindows/CVI Programmer Reference Manual
Chapter 1LabWindows/CVI Compiler
At this time, not all these qualifiers work in all external compilers. The LabWindows/CVI
cvidef.h include file defines the following macros, which are designed to work in each
external compiler.
DLLIMPORT
DLLEXPORT
An import qualifier informs the compiler that the symbol is defined in a DLL. Declarations
of variables imported from a DLL r equi r e import qualifiers , but function declarat i o ns do n ot .
An export qualifier is relevant only in a project for which the target type is Dynamic Link
Library. The qualifier can be on the declaration or definition of the symbol, or both. The
qualifier instructs the linker to include the symbol in the DLL import library.
C++ Comment Markers
You can use doub le slashes (/ /) to be gin a comment. The comment continues until the end of
the line.
Duplicate Typedefs
The LabWindows/CVI compiler does not report an error on multiple definitions of the same
typedef identifier, as long as the definitions are identical.
Structure Packing Pragma (Windows 3.1 and Windows 95/NT Only)
The packpragma can be used within LabWindows/CVI to specify the m aximum alignment
factor for elements within a structure. For exam ple, assume the following structur e definition:
struct t {
double d1;
char charVal;
short shortVal;
double d2;
};
If the maximum alignment is 1, the compiler can start the structure on any 1-byte boundary
and inserts no gaps between the structure elements.
If the maximum alignment is 8, the compiler must start the structure on an 8-byte boundary,
shortVal on a 2-byte boundary, and place d2 on an 8-byte boundary.
#pragma pack(4) /* sets maximum alignment to 4 bytes */
#pragma pack(8) /* sets maximum alignment to 8 bytes */
#pragma pack() /* resets to the default*/
The maximum alignment the compiler applies to a structure is based on the last pack
pragma
statement it sees before the definition of the structure.
Program Entry Points (Windows 95/NT Only)
Under Windows 95/NT, you can u se WinMain instead of main as the entry-point function to
your program. You might want to do this if you pl an to li nk your ex ecutable using an exte rnal
compiler. You must include
WinMain parameter list. The following is the prototype for WinMain with the W indo ws data
windows.h for the data types that normally appear in the
types reduced to intrinsic C types.
int __stdcall WinMain(void * hInstance, void * hPrevInstance,
char * lpszCmdLine int nCmdShow)
C Library Issues
This section discusses special considerations in LabWindows/CVI in the areas of low-level
I/O functions and the UNIX C library.
Chapter 1LabWindows/CVI Compiler
Using the Low-Level I/O Functions
Many functions in the UNIX libraries and the C compiler libraries for the PC are not ANSI C
Standard Library functions. In general, LabWindows/CVI implements the ANSI C Standard
Library. Under UNIX, you can call UNIX libraries for the non-ANSI C functions in
conjunction with LabWindows/CVI.
The low-level I/O functions
ANSI C Standard Library . Under UNIX, these functions are av ailable in the UNIX C library .
Refer to Chapter 5, UN IX Compiler /Linker Issues, for more information.
Under Windows, you can use these functions along with
The size of an enumeration type depends on the value of its enumeration constant.
In LabWindo ws/CVI, characters are
The types
float and double conform to 4-byte and 8-byte IEEE standard formats.
signed, unless you explicitly declare them unsigned.
Converting 16-Bit Source Code to 32-Bit Source Code
If you convert a LabWindows for DOS application to a LabWindows/CVI application, use
this section as a guide after you complete the steps in Chapter 12, Converting LabWindows for DOS Applications, of the Getting Started with LabWindows/CVI manual.
In general, if you make few assumptions about the sizes of data types, little difference exists
between a 16-bit compiler and a 32-bit compiler except for the lar ger capacity of integers and
the larger address space for arrays and pointers.
declares a 2-byte integer in a 16-bit compiler such as LabWindows for DOS. In contrast,
a 32-bit compiler such as LabWindows/CVI handles this code as a declaration of a 4-byte
integer. In most cases, this does not cause a problem and the conversion is transparent,
because functions that use 2-byte integers in LabWindows for DOS use 4-byte integers in
LabWindo ws/CVI. Howe ver , this con version does cause a problem when a prog ram performs
one of the following actions:
•Passes an array of 16-bit integers to a GPIB, VXI, or Data Acquisition (DAQ) function
If you use a 32-bit
int array to receive a set of 16-bit integers from a device,
LabWindows/CVI packs two 16-bit values into each element of the 32-bit array. Any
attempt to access the array on an element-by-element basis does not work. Declare the
array as
short instead, and make sure any type specifiers that refer to it have the [b2]
modifier when you pass them as an argument to a Formatting and I/O Library function.
•Uses an
For example, if yo u pass an
I/O Library, such as a
%i[b2] specifier, it does not work correctly. Remove the [b2] modifier, or declare the
variable as
Conver sely , if you pass a
without the
int variable in a way that requires it to be a 2-byte integer
int argument by address to a function in the Formatting and
Scan source or a Scan/Fmt target, and it matches a %d[b2] or
short.
short argument by address and it matches a %d or %i specifier
[b2] modifier, it does not work correctly. Add the [b2] modifier.
NoteThe default for %d is 2 bytes on a 16-bi t compil er and 4 bytes on a 32-bi t compil er.
In the same way, the default for
int is 2 bytes on a 16-bit compiler, and 4 bytes on
a 32-bit compiler. This is why you do not have to make any m odifications if the
specifier for a variable of type
int is %d without the b
All pointers are 32-bit offsets. LabWindows/CVI does not use the
n
modifier.
far pointers that have both
a segment selector and an offset, except in 16-bit Windows DLLs under Windows 3.1.
LabWindows/CVI for Windows 3.1 calls 16-bit DLLs through a special interface
LabWindo ws/CVI generates fro m the header file for the DLL. For more information, refer to
the Using 32-Bit Watcom Compiled Mod ule s under Windows 3.1 and 16-Bit Windows DLLs
sections in Chapter 4, Windows 3.1 Compiler/Linker Issues.
National Instruments Corporation1-7LabWindows/CVI Programmer Reference Manual
Chapter 1LabWindows/CVI Compiler
Debugging Levels
Y o u can compile the source modules in your app lication to include debu gging information. If
you do so, you can us e breakpo ints and view or modify v a riables and e xpres sions while y our
program is suspended. You set the debugging level by selecting Options»Run Option s in the
Project window. Refer to the Run Options section in Chapter 3, Project Window, of the LabWindows/CVI User Manual for information on debugging levels.
User Protection
User protection detects invalid program behavior that LabWindows/CVI cannot otherwise
detect during compilation. LabWindows/CVI reports such invalid program behavior as user
protection errors. When you set the debugging level to Standard or Extended,
LabWindows/CVI maintains extra information for arrays, structures, and pointers, and uses
the information at run time to determine the validity of addresses.
Two groups of user protection errors exist based upon two characteristics: severity level and
error cate gory. In each case, the ANSI C standard states that programs with these errors have
undefined behavior. The two severity levels are as follows:
•Non-Fatal errors include expressions that are likely to cause problems, but do not
directly affect program execution. Examples include b ad pointer ar ithmetic, attempts to
free pointers more than once, and comparisons o f pointers to different ar ray objects. The
expression is invalid and its behavior is undefined, but execution can continue.
•Fatal errors include expressions that LabWindows/CVI cannot execute without causing
major problems, such as causing a general protection fault. For example, dereferencing
an invalid pointer value is a fatal error.
Error categories include pointer protection, dynamic memory protection, library protection,
and general protection errors. Each of these categories includes subgroups as described in the
following sections.
Array Indexing and Pointer Protection Errors
The pointer protection errors catch invalid operations with pointers and arrays. In this section,
these errors are grouped by the type of expr ession that causes the error or the type of invalid
pointer involved.
Pointer Arithmetic (Non-Fatal)
Pointer arithmetic expressions involve a pointer sub-expression and an integer
sub-expression . LabWindows/CVI generates a n error when the pointer sub-expression is
invalid or when the arithmetic operation results in an invalid pointer expression. The
following user protection errors involve pointer arithmetic:
•Pointer arithmetic involving u ninitialized pointer
•Pointer arithmetic involving n ull pointer
•Out-of-bounds pointer arithmetic (calculation of an array address that results in a pointer
value either before the start, or past the end of the array)
•Pointer arithmetic involving pointer to freed memory
•Pointer arithmetic involving in valid pointer
•Pointer arithmetic involving address of non-array object
•Pointer arithmetic involving p ointer to function
•Array index too large
•Negative array index
Pointer Assignment (Non-Fatal)
LabWindows/CVI generates pointer assignment errors when you assign invalid values to
pointer variables. These warnings can help determine when a particular pointer becomes
invalid. The following user protection errors involve pointer assignment:
•Assignment of uninitialized pointer value
•Assignment of out-of-bounds pointer expression (assignment of an address before the
start, or past the last element, of an array)
•Assignment of pointer to freed memory
•Assignment of invalid pointer expression
Pointer Dereference Errors (Fatal)
Dereferencing of inv alid pointer v alues is a fatal error because it can cause a memory f ault or
other serious problem. The following user protection errors involve pointer dereferencing:
•Dereference of uninitialized pointer
•Dereference of null pointer
•Dereference of out-of-bounds po inter (dereference using a pointer valu e before the start,
or past the end, of an array)
•Dereference of pointer to freed memory
•Dereference of invalid pointer expression
•Dereference of data pointer for use as a function
National Instruments Corporation1-9LabWindows/CVI Programmer Reference Manual
Chapter 1LabWindows/CVI Compiler
•Dereference of a pointer to an n-byte type where less than n bytes exist in the object
•Dereference of unaligned pointer (UNIX only)
Pointer Comparison (Non-Fatal)
LabWindows/CVI generates pointer comparison errors for erroneous pointer comparison
expressions. The following user protection errors involve pointer comparison:
•Comparison involving uninitialized pointer
•Comparison involving null pointer
•Comparison involving invalid pointer
•Comparison of pointers to different objects
•Pointer comparison involving address of non-array object
•Comparison of pointers to freed memory
Pointer Subtraction (Non-Fatal)
LabWindows/CVI generates pointer subtraction errors for erroneous pointer subtraction
expressions. The following user protection errors involve pointer subtraction:
•Subtraction involving unin itialized pointer
•Subtraction involving null pointer
•Subtraction involving invalid pointer
•Subtraction of pointers to different objects
•Pointer subtraction involving address of non-array object
•Subtraction of pointers to freed memory
Pointer Casting (Non-Fatal)
LabWindows/CVI generates a pointer casting error when you cast a pointer expression to type
AnyType *) and not enough space exists for an object of type AnyType at the location the
(
pointer expression specifi es. This occurs only when casting a dynamically allocated object fo r
the first time, such as with the code
LabWindows/CVI reports the following error:
Dynamic memory protection errors report illegal operations with dyna mi c memory and
corrupted dynamic memory during allocation and deallocation.
Memory Deallocation (Non-Fatal)
LabWindows/CVI generates memory deallocation errors when the pointer is not the result of
a memory allocation. The following user protection errors involve memory deallocation:
•Attempt to free uninitialized pointer
•Attempt to free pointer to freed memory
•Attempt to free invalid pointer expression
•Attempt to free pointer not allocated with
Memory Corruption (Fatal)
LabWindows/CVI generates memory corruption errors when a memory
allocation/deallocation detects corrupted memory. During each dynamic memory operation,
LabWindows/CVI verifies the integrity of the memory blocks it uses in the operation. When
you set the Debuggi ng Level to Exten ded, LabWindo ws/C VI thor oughl y checks al l dynami c
memory on each memory oper ation. LabW in do ws/CVI generates the follo wing erro r when it
discovers a problem:
Dynamic memory is corrupt.
Chapter 1LabWindows/CVI Compiler
malloc or calloc
General Protection Errors
LabWindows/CVI also checks for stack overflow and missing return values:
•Stack overflow (fatal)
•Missing return value (non-fatal)
The missing return value error means that a non-void function (one you do not declare with
void return type) returned, but did not returned a value.
Library Protection Errors
Library functions sometimes generate errors when they receive invalid arguments.
LabWindows/CVI error checking is sensitive to the requirements of each library function.
The following errors involve library protection:
•Null pointer argument to librar y function
•Uninitialized pointer argument to library function
•Passing a pointer to freed memory to a library function
•Array argument too small
•Passing by reference a scalar argument to a library function that expects an array
National Instruments Corporation1-11LabWindows/CVI Programmer Reference Manual
Chapter 1LabWindows/CVI Compiler
•Missing terminating null in string argument
•Passing a string to a library function that expects a character reference parameter
LabWindows/CVI libr ary functions retu rn error codes in a v ariety of cases. If you enable the
Break on Library Errors option in the Run Options command in the Options menu of the
Project window , LabW indows/CVI suspends execution after a library function returns one of
these errors. A message appears that displays the name of the function and either the return
value or a string that explains why the function failed.
Disabling User Protection
Occasionally, you might want to disable user protection to avoid run-time errors that do not
cause problems in your program.
Disabling Protection Errors at Run-Time
You can use the SetBreakOnProtectionErrors function in the Utility Library to
programmatically control whether LabWindo ws/CVI suspends ex ecution when it encounters
a protection error. This function does not affect the Break on Library Errors feature.
Disabling Library Errors at Run-Time
The Break on Library Errors option in the Run Options command in the Options m enu of
the Project window lets you choose whether LabWindows/CVI suspends execution when a
library function returns an error code. The option takes effect when you start executing the
project. You can override the initial setting in your program by using the
SetBreakOnLibraryErrors function in the Utility Library. Use of this function does not
affect the reporting of other types of library protectio n errors.
Disabling Protection for Individual Pointer
You can disable pointer checking for a particular pointer by casting it first to an arithmetic
type and then back to its original type, as shown in the following macro:
char *charPointer;
/* run-time checking is performed for charPointer before this
line */
DISABLE_RUNTIME_CHECKING(charPointer);
/* no run-time checking is performed for charPointer after this
line */
This macro could be useful in the following situation: LabWindows/CVI reports erroneous
run-time errors because you set a pointer to d ynamic memory in a source module and you th en
resize it in an object module. The following steps describe how this error occurs:
1.Y o u declare a pointer in a source module you compile with debu gging enabled. You then
assign to the pointer an address that
AnyType *ptr;
ptr = malloc(N);
malloc or calloc returns:
2.You reallocate the pointer in an object module so that it points to the same location in
memory as before. This might occur if you call the
and then reassign it to memory that you allocate with
ptr = realloc(ptr, M); /* M > N */
realloc function or free the pointer
malloc:
or
free(ptr);
ptr = malloc(M);
3.You use the same pointer in a source module you compile with debugging enabled. At
this point, LabWindows/CVI still expects the pointer to point to a block of memo ry of
the original size
*(ptr+(M-1))/* This generates a fatal run-time error, */
(N).
/* even though it is a legal expression. */
To prevent this error, use the DISABLE_RUNTIME_CHECKING macro to disable checking for
the pointer after you allocate memory for it in the source module:
ptr = malloc(N);
DISABLE_RUNTIME_CHECKING(ptr);
Disabling Library Protection Errors for Functions
You can disable or enable library protection errors by placing pragmas in the source code.
LabWindo ws/CVI ignores t hese prag mas when y ou compil e without deb ugging informati on,
that is, if the debugging level is None. For example, the following two pragmas enable and
disable library checking for all the function declarations that occur after the pragma within a
header or source file. The pragmas affect only the functions declared in the file in which the
pragmas occur. These pragmas do not affect nested include files.
The following pragmas enable and disable library checking for a particular function. You
must declare the function before the occurrence of the pragma.
#pragma EnableFunctionRuntimeChecking function
#pragma DisableFunctionRuntimeChecking function
National Instruments Corporation1-13LabWindows/CVI Programmer Reference Manual
Chapter 1LabWindows/CVI Compiler
These two pragmas enable and disable run-time checking for a particular library function
throughout the module in which they appear. You can use them to override the effects of the
EnableLibraryRuntimeChecking and DisableLibraryRuntimeChecking pragmas
for individual functions. If both of these pragmas occur in a module for the same function,
LabWindows/CVI uses only the last occurrence.
NoteThese pragmas affect all protection, including run-time checking of function
arguments, for all calls to a specific library function. To disable breaking on
errors for a particular call to a library function, use the Utility Library function
SetBreakOnLibraryErrors. To disable the run-time checking of argument
expressions for a particular ca ll to a library function, use the Utility Library
function
NoteYou cannot use prag mas to disable protection for the functio ns in the
SetBreakOnProtectionErrors.
statically linked libraries including User Interface, RS-232, TCP, DDE,
Formatting and I/O, Utility, X Property, and ANSI C libraries unless you place the
DisableLibraryRuntimeChecking pragma at the top of the library header file.
Details of User Protection
Pointer Casting
A cast expression consists of a left parenthesis, a type name, a right parenthesis, and an
operand expression. The cast causes the compiler to convert the operand v alue to the type that
appears within the parenthesis.
C programmers occasionally have to cast a pointer to one data type to a pointer to another data
type. Because LabWindo ws/CVI does not restructure the user protection information for each
cast expression, certain types of cast expressions implicitly disable run-time checking for the
pointer value. In particular, casting a pointer expression to the following types disables
run-time checking on the resulting value:
•Pointer to a pointer:
(AnyType **) PointerExpression
•Pointer to a structure:(struct AnyStruct *) PointerExpression
LabWindows/CVI provides run-time error checking for pointers and arrays in dyna m ically
allocated memory.
You can use the ANSI C library functions
These functions return
void * values that you must cast to some other type before the
malloc or calloc to allocate dynamic memory.
memory can be used. During program execution, LabWindows/CVI uses the first such cast
on the return value of each call to these functions to determine the type of the object that will
be stored in the dynamic memory. Subsequent casts to different types can disable checking on
the dynamic data, as explained in the Pointer Casting discussion in this section.
You can use the
realloc function to resize dynamically allocated memory. This function
increases or decreases the size of the object associated with the dynamic memory.
LabWindows/CVI adjusts the user protection information accordingly.
Avoid Unassigned Dynamic Allocation in Function Parameters
The LabWindows/CVI run-time error checking mechanism dynamically allocates data to
keep track of pointers that you dynamically allocate in your program. When you no longer
use the pointers, LabWindows/CVI uses garbage collection to deallocate its corresponding
dynamic memory.
A case exists where the garbage collection fails to retrieve all the memory it allocated. This
occurs when you pass the return value of one function to another function, the return value is
a pointer to dynamically allocated memory, and you do not assign the pointer to a variable in
the argument expression. The following is an example:
MyFunc (1, 2, malloc(7));
This call passes the return value from malloc to MyFunc but does not assign it to a variable.
If you make this call repeatedly in your program with run-time checki ng enabl ed, you lose a
small amount of memory each time.
Change the code as follows to avoid this problem.
void *p;
MyFunc (1, 2, p = malloc(7));
The following code also works and uses better programming style.
National Instruments Corporation1-15LabWindows/CVI Programmer Reference Manual
Chapter 1LabWindows/CVI Compiler
Library Functions
The LabWindows/CVI library functions that take pointer arguments or that return pointers
incorporate run-time checking f or those arguments and return values. Howe ver, yo u mu st be
careful when passing arguments to library functions that have
GetCtrlAttribute and GetCtrlVal in the User Interface Library and memcpy and
memset in the ANSI C library. If you use a void * cast when you pass an argument to a
function that expects a variably typed argument, you disable run-time checking for that
argument. Some examples follow:
{
int value;
GetCtrlVal(panel, ctrl, &value);/* CORRECT */
LabWindows/CVI performs only minimal checks for
contains pointers, arrays, or structs, LabWindows/CVI does not maintain user protection
information for those objects.
Stack Size
Your program uses the stack for passing function parameters and storing automatic local
variables. You can set the maximum stack size by selecting the Options»Run Option s in the
Project window. Table 1-3 shows the stack size ranges LabWindows/CVI supports.
Windows 3.14 KB40 KB40 KB
Windows 95/NT100 KB250 KB1 MB
Solaris 1 for Sun100 KB250 KB5 MB
Solaris 2 for Sun100 KB250 KB5 MB
NoteFor LabWindows/CVI for Windows 3.1, the actual stack size approaches 64 KB
when you set the Debugging level to None.
Include Paths
The Include Paths command in the Options menu of the Project window specifies the
directory search path for include files. The Include Paths dialog box has two lists, one for
include paths specific to the project, and one for paths not specific to the project.
When you install VXIplug&play instrument drivers, the installation program places the
include files for the driv ers in a specif ic VXIplug&play include directory . LabWindo ws/CVI
also searches that directory for include files.
Include Path Search Precedence
LabWindows/CVI searches for include files in the following locations and in the
following order:
1.Project list
2.Project-specific include paths
3.Non-project-specific include paths
4.The paths listed in the Instru ment Directories dialog box
National Instruments Corporation1-17LabWindows/CVI Programmer Reference Manual
Using Loadable
Compiled Modules
This chapter describes the advantages and disadv an tag es of using compiled code modules in
your applicatio n. It also describes the kinds of compiled modules available in
LabWindows/CVI and includes programming guidelines for modules you generate with
external compilers.
Refer to Chapter 3, Windows 95/NT Compiler/Linker Issues, Chapter 4, Windows 3.1
Compiler/Linker Issues, or Chapter 5, UNIX Compiler/Linker Issues, in this manual for more
information on platform-specific programming guidelines for modules that external
compilers generate.
About Loadable Compiled Modules
Several methods exist for using compiled modules in LabWindows/CVI. You can load
compiled modules directly into the LabWindows/CVI environment as instrument driver
programs or as user libraries, so they are accessible to any project. You can list compiled
modules in your project, so they are accessible only within that project. You can use compiled
modules dynamically in your program with
UnloadExternalModule. Any comp iled module you use in Lab W indo ws/CVI must b e
and
in one of the following forms:
•A
.obj file on the PC, or a .o file under UNIX, that contains one object module
•A
.lib file on the PC, or a .a file under UNIX, that contains one or more object modu les
•A
.dll file that contains a Windows DLL (Windows only)
LoadExternalModule, RunExternalModule,
2
You can create any of these compiled modules in LabWindows/CVI under Windows 95/NT,
or using a compatible external compiler. Under Windows 3.1, LabWindows/CVI can create
.obj files. Under UNIX, LabWindows/CVI can create only .o files.
National Instruments Corporation2-1LabWindows/CVI Programmer Reference Manual
Chapter 2Using Loadable Compiled Modules
Advantages and Disadvantages of Using Loadable Compiled Modules
inLabWindows/CVI
Using compiled modules in LabWindows/CVI has the following advantages:
• Compiled modules run faster than source modules. Compi led modules do not contain t he
debugging and user protection code LabWindows/CVI generates when it compiles
source modules. Compiled modules you generate in external compilers can run faster
because of optimization.
• LabWindows/CVI recompiles the source modules in a project each time you open the
project. Also, if an instrument driver pro gram file is a source modul e, LabWindows/CVI
recompiles it each time you load the instrument driver. LabWindows/CVI does not
recompile compiled modules when you open a project or load an instrument driver.
• In standalone executables, you can dynamically load compiled modules but not source
modules.
• You can install compiled modules, but not source modules, into the Library menu.
• You can provide libraries for other developers without giving them access to your source
code.
Using compiled modules in LabWindows/CVI has the following disadvantages:
• You cannot debug compiled modules. Because compiled modules do not contain any
debugging information, you cannot set breakpoints or view variable values.
• Compiled modules do not include run-time error checking or user protection.
Using a Loadable Compiled Module as an Instrument Driver
ProgramFile
An instrumentdriver is a set of high-level functions w ith graphical function panels to make
programming easier. It encapsulates many low-level operations, such as data formatting and
GPIB, RS-232, and VXI communication, into intuitive, high-level functions . An instrument
driver usually controls a physical instrument, but it also can be a software utility. The Using
Instrument Drivers and Instrument Menu sections of Chapter 3, Project Window, of the
LabWindows/CVI User Manual describe how to use instrument drivers.
To develop and debug an instrument driver, load its program file into LabWindows/CVI as a
source file. After you finish debugging it, you can compile the program file into an object file
or a Windows 95/NT DLL. The next time you load the instrument driver, LabWindows/CVI
loads the compiled module, which loads and runs faster that the source module.
Refer to the LabWindows/CVI Instrument Driver Developers Guide for information on how
to create an instrument driver.
If the instrument driver program file is a compiled module, it must adhere to the requirements
outlined for each operating system in Chapter 3, Windows 95/NT Compiler/Linker Issues,
Chapter 4, Windows 3.1 Compiler/Linker Issues, and Chapter 5, UNIX Compiler/Linker
Issues, of this manual.
Using a Loadable Compiled Module as a User Library
You can install your own libraries into the Library menu. A user library has the same form
as an instrument driver. You can load as a user library anything that you can load into the
Instrument menu, provided the progr am is in com pile d form. Refer t o the Using Instrument
Drivers and the Instrument Menu sections of Chapter 3, Project Window, of the
LabW indows /CVI Use r Manua l for more information. The main dif ference between modules
you load as instrument drivers and those you load as user libraries is that you can unload
instrument drivers using the Unload command in the Instrument menu, but you cannot
unload user libraries. You cannot edit and recompile user libraries while they are loaded.
Install user libraries by selecting the Library Options command in the Project Options
menu. The next time you run LabWindows/CVI, the libraries load automatically and appear
at the bottom of the Library menu.
You can de v e lop a user li brary mod ule to pro vi de sup port fu nction s for in stru ment drivers or
any other modules in your project. By installing a module through the Library Options
command, you ensure that the library is always available in the LabWindows/CVI
developmen t environmen t. If you do not want to de velop function pan els for the library , create
.fp file without any classes or functions. In that case, LabWindows/CVI loads the library
a
at startup but does not include the library name in th e Library menu.
User libraries must adhere to the requirements outlined for the target operating system.
Chapter 3, Windows 95/NT Compiler/Linker Issues, Chapter 4, Windows 3.1
Compiler/Linker Issues, and Chapter 5, UNIX Compiler/Linker Issues, of this manual, discuss
operating system requirements.
Using a Loadable Compiled Module in the Project List
You can include compiled modules directly in the project list.
Note
Even when you inclu de a source module in the project list, you can instruct LabW indo ws/CVI
to create an object module on disk when it compiles the file instead of debuggable code in
memory. To do this, double click in the O column next to the source file in the Project window.
National Instruments Corporation2-3LabWindows/CVI Programmer Reference Manual
To use a DLL in your project under Windows 95/NT, you must include the DLL
import library (
.lib) file in the project list rather than the DLL.
Chapter 2Using Loadable Compiled Modules
Compiled modules must adhere to the requirements outlined for the target operating
system. Chapter 3, Windows 95/NT Compiler/Linker Issues, Chapter 4, Windows 3.1
Compiler/Linker Issues, and Chapter 5, UNIX Compiler/Linker Issues, of this manual, discuss
operating system requirements.
Using a Loadable Compiled Module as an External Module
You can load a compiled module dynamically from your program. A module you load
dynamically is called an external module. You can load, execute, and unload this external
module programmaticall y us in g
UnloadExternalModule. Refer to Chapter 8, Utility Library, of the LabWindows/CVI
LoadExternalModule, GetExternalModuleAddr, and
Standard Libraries Reference Manual for more information on using these functions.
While you develop and debug the external module, you can list it in the project as a source
file. After you finish debugging the module, you can compile it into an object file or a
Windows 95/NT DLL. External modules must adhere to the requirements outlined for the
target operating system. Chapter 3, Windows 95/NT Compiler/Linker Issues, Chapter 4,
Windows 3.1 Compiler/Linker Issues, and Chapter 5, UNIX Compiler/Linker Issues, of this
manual, discuss operating system requirements.
Notification of Changes in Run State
You migh t ha ve to no tify cert ain compile d modules whene v er your pr ogram starts , suspends,
continues, or stops. For example, if a co mpiled module has asynchronous callbacks, yo u must
prevent the callbacks from executing when program execution suspends at a breakpoint.
LabWindows/CVI has a callback mechanism you can use to inform a compiled module of
changes in the program status.
To notify a compiled module of changes in the run state, add a function with the name
__RunStateChangeCallback to the compiled module. LabWindows/CVI automatically
installs the callback for you.
The run state change callback must be in a compiled file, not in a source file. More than one
compiled module can contain functions with this name, because LabWindows/CVI never
enters it into the global name space. The prototype for the callback is as follows:
/* program execution suspends; CVI environment resumes */
.
.
.
/* user selects the Terminate Execution command */
kRunState_DisableCallbacks /* even though callbacks already
kRunState_AbortingExecution
/* long jump out of user program */
kRunState_DisableCallbacks /* even though callbacks already
kRunState_Stop
disabled */
disabled */
Note
A Resume notification does not always follow a Suspend notification. A Stop
notification can follow a
Suspend notification without an intervening Resume
notification.
Note
Run state change callbacks do no t work if you link your program in an external
compiler. Also, external compilers report link errors if you have multiple run state
change callbacks.
Using Run State Change Callbacks in a DLL
You can include one or more run state change callbacks in a DLL. To do so, you must build
the DLL in the LabWindows/CVI development environment, and each run state change
callback must be in a separate object or static library file in the DLL project. I f you include a
run state change callback in a DLL, or in an object or s tatic library f ile that another user migh t
include in a DLL, take special care in two areas:
•Use caution when you call in to other DLLs in respo nse to a
When you use your DLL in a standalone executable, the DLL receives the
kRunState_Stop message when the executable terminates. The order in which
Windo ws 95/NT unlo ads DLLs at process termi nation is not well-d efined. Therefo re, the
DLL you call into might no longer be loaded. This can cause a general protectio n fault.
Nevertheless, when you use your DLL in a program in the LabWindows/CVI
development environment, it is often necessary to call into DLLs to release resources
after each run. To solve this dilemma, use conditional code to release resources only if
you are running in the LabWindows/CVI development environment. An example
follows.
#include <utility.h>
switch (runState)
{
case kRunState_Stop:
if (! InStandaloneExecutable())
{ /* call into other DLLs to release resources */ }
/* release resources, including unloading DLLs */
break;
}
It is always safe to call into the LabW indo ws/CVI Run- time Engine in a run state change
callback.
•If your DLL uses global v ariables that can become stale after each prog ram e xecution in
the LabWindows/CVI development environment, re-initialize the variables in response
kRunState_Start or kRunState_Stop message. For example, memory that
to the
you allocate using L abWin dows/CVI ANSI C functions such as
malloc or calloc is no
longer valid when you restart your program. If your DLL h a s gl ob al variables th at point
to allocated memory, set those pointers to
kRunState_Stop message.
or
NULL in response to the kRunState_Start
Compiled Modules that Contain Asynchronous Callbacks
A compiled module can call a source code function asynchronously. This can happen throu gh
interrupts or signals. In Windows 95/NT, the compiled module can call the source code
function from a thread other than the main thread. The call takes place asynchronously with
respect to the normal execution of the source code in your program.
The execution and debugging system in the LabWindows/CVI development environment is
not prepared to handle this asynchronous execution. Consequently, the compiled module must
announce to LabWindows/CVI that it is calling asynchronously into source code. It does this
by calling
ExitAsyncCallback
ExitAsyncCallback have one parameter, which is a pointer to a buffer of size
ASYNC_CALLBACK_ENV_SIZE. Yo u must pass the same buffer into ExitAsyncCallback
National Instruments Corporation2-7LabWindows/CVI Programmer Reference Manual
EnterAsyncCallback before calling the function, and calling
after calling the function. EnterAsyncCallback and
EnterAsyncCallback because the buff er stores state information. The
ASYNC_CALLBACK_ENV_SIZE and the prototypes for these two functions are
Windows 95/NT
Compiler/Linker Issues
This chapter describes the different kinds of compiled modules available under
LabWindows/CVI for Wi n dows 95/NT and includes programming guidelines
for modules you generate with ext ern al compi lers.
Under Windows 95/NT, the LabWindows/CVI compiler is compatible with four external
32-bit compilers: Microsoft Visual C/C++, Borland C/C++, Watcom C/C++, and
Symantec C/C++. This manual refers to the four compilers as the compatible external compilers.
In LabWindows/CVI under Windows 95/NT, you can do the following:
•Load 32-bit DLLs, through the standard import library mechanism
•Create 32-bit DLLs and DLL import libraries
•Create library files and object files
•Call the LabWindows/CVI libraries from executables or DLLs created with any of the
four compatible external compilers
•Create object files, library files, and DLL import libraries that the compatible external
compilers can use
•Load object files, library files, and DLL import libraries created with any of the four
compatible external compilers
•Call Windows Software Development Kit (SDK) functions
3
This chapter discusses these capabilities.
Loading 32-Bit DLLs under Windows 95/NT
Under Windows 95/NT, LabWindows/CVI can load 32-bit DLLs. LabWindows/CVI links to
DLLs through the standard 32-bit DLL import libraries that you generate when you create
32-bit DLLs with any of the compilers. Because LabW indo ws/CVI links to DLLs in this way,
you cannot specify a DLL file directly in your project. You must specify the DLL import
library file instead.
National Instruments Corporation3-1LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
DLLs for Instrument Drivers and User Libraries
Under Windo ws 9 5/NT, LabW in dows /CVI does not dir ectly associ ate DLLs with in strument
drivers or user libraries. However, LabWindows/CVI can associate instrument drivers and
user libraries with DLL import libraries. Each DLL must have a DLL import library (
file. In general, if the program for an instrumen t driver or user library is in the form of a DLL,
you must place the DLL import library in the same directory as the function panel (
The DLL import library specifies the name of the DLL that LabWindows/CVI searches for
using the standard Windows DLL search algorithm.
LabWindows/CVI makes an exception to facilitate using VXIplug&play instrument driver
DLLs. When you install a VXIplug&play instrument driver, the installation program
does not place the DLL import library in the same directory as the
is in the VXIplug&play directory, LabWindows/CVI searches for an import library in
the VXIplug&play library directory before it looks for a program file in the directory of
.fp file, unless you list the program file in the project.
the
Using The LoadExternalModule Function
When you use the LoadExternalModule function to load a DLL at run time, you must
specify the pathname of the DLL import library, not the name of the DLL.
.lib)
.fp) file.
.fp file. If a .fp file
Link Errors when Using DLL Import Libraries
A DLL import library must not contain any references to symbols that the DLL does not
export. If it does, LabWindows/CVI reports a link error. If you load the DLL using
LoadExternalModule, the GetExternalModuleAddr function reports an undefined
references (
import library. Refer to the Generating an Import Library discussion later in this section.
–5) error. You can solve this problem by using LabWindows/CVI to generate an
DLL Path (.pth) Files Not Supported
The DLL import library contains the filename of the DLL. LabWindows/CVI uses the
standard Windows DLL search algorithm to find the DLL. Thus, DLL path (
files do not work under Windows 95/NT.
16-Bit DLLs Not Supported
LabWindows/CVI for Windows 95/NT does not load 16-bit DLLs. If you want to do this, you
must obtain a 32-to-16-bit thunking DLL and a 32-bit DLL import library.
Run State Change Callbacks in DLLs
You can include run state change callbacks in DLLs you build in LabWindows/CVI. When
running a program in LabWindows/CVI, a run state change callback receives notification
when the program starts, suspends, resumes, and stops. If you include a run state change
callback in a DLL, you must take special care. Refer to the Notification of Changes in Run
State section in Chapter 2, Using Loadable Compiled Modules, of this manual, for a detailed
discussion of run state change callbacks.
DllMain
Each DLL can have a DllMain function, except that the Borland compiler uses
DllEntryPoint as the name. The operating system calls the DllMain function with various
messages. To generate the template for a
command in the Edit menu of a Source w indow.
Chapter 3Windows 95/NT Compiler/Linker Issues
DllMain function, use the Insert Constructs
Use caution when inserting code in the
PROCESS_ATTACH and PROCESS_DETACH cases. In
particular, avoid calling into other DLLs in these two cases. The order in which
Windows 95/NT initializes DLLs at startup and unl oads them at process termination is not
well-defined. Thus, the DLLs you want to call might not be in memory when your
receives the
PROCESS_ATTACH or PROCESS_DETACH message.
It is always safe to call into the LabWindows/CVI Run-time Engine in a run state change
callback, as long as you do so before calling
CloseCVIRTE.
Releasing Resources when a DLL Unloads
When a program terminates, the operating system disposes resources your DLL allocates. If
your DLL remains loaded throughout program execution, it does not need to dispose
resources explicitly when the system unloads it at program termination. However, if the
program unloads your DLL during program execution, it is a good idea for your DLL to
dispose of any resources it allocates. It can release resources in the
response to the
that it registers with the ANSI C
when the DLL receives the
If your DLL calls into the LabWindo ws/CVI Run-time Engine DLL, it can allocate resources
such as user interface panels. If a program unloads your DLL during execution, you might
want to dispose these resources by calling functions such as
LabWindo ws/CVI R un-tim e Engine. On the ot her hand, as e xplaine d in the pre viou s section,
it is generally unsafe to call into other DLLs in response to the
PROCESS_DETACH message. The DLL can also release resources in a function
atexit function. The system calls the function you register
PROCESS_DETACH message.
DllMain
DllMain function in
DisposePanel in the
PROCESS_DETACH message.
To solve this dilemma, you can use the
Utility Library. It is always safe to call the
CVIRTEHasBeenDetached returns FALSE until the main Run-time Engine DLL,
cvirte.dll, receives the PROCESS_DETACH message. Consequently, if
CVIRTEHasBeenDetached returns FALSE, your DLL can safely call functions in
CVIRTEHasBeenDetached function in the
CVIRTEHasBeenDetached function.
LabWindows/CVI Run-time Engine to release resources.
National Instruments Corporation3-3LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
Notecvirte.dll contains the User Interface, Utility, Formatting and I/O, RS-232,
ANSI C, TCP, and DDE Libraries.
Generating an Import Library
If you do not have a DLL import library or if the one you have contains references the DLL
does not export, you can generate an import library in LabWindows/CVI. You must have an
include file that contains the declarations of all the functions and global v ariables you want to
access from the DLL. The calling conventions of the function declarations in the include file
must match the calling convention of the functions in the DLL. For example, if the DLL
exports functions using the
include file must contain the
window, and select the Generate DLL Import Library command in the Options menu.
__stdcall calling convention, the function declarations in the
__stdcall keyword. Load the include file into a Source
Default Unloading/Reloading Policy
Some fundamental differences exist in the way Windows 95/NT and Windows 3.1 handle a
DLL that multiple processes use.
Windows 95/NT creates a separate data space for each process that uses the DLL.
Windows 3 .1 creates only one data space for all processes that use the DLL.
Windows 95/NT notifies a DLL each time a process loads or unloads it. Windows 3.1 does
not notify a DLL each time a process loads or unloads it. Windo ws 3.1 n otif ies the DLL on ly
when the first process loads it and the last process unloads it.
LabWindows/CVI for Windows 95/NT unloads DLLs, by default, after each execution of a
user program in the development environment. This behavior more accurately simulates
what happens when you execute a standalone executable, and it is more suitable for
Windo ws 95/NT DLLs that rely on load/unload notification on each ex ecution of a program.
You can change the def ault beha vi or by turning of f the Unload DLLs After Each Run option
in the Run Options dialog box of the Project window. National Instruments recommends,
however, that you leave the default behavior in effect.
Compatibility with External Compilers
LabWindows/CVI for Windows 9 5/ NT can be compatible at the object code level with
any of the four compatible external compilers (Microsoft Visual C/C++, Borland C/C++,
Watcom C /C++, and Symantec C/C++). Because these compilers are not compatible with
each other at the object code level, LabWindows/CVI can be compatible with only one
external compiler at a time. This manual refers to the compiler with which your copy of
LabWindows/CVI is currently compatible as the current compatible compiler.
When installing LabWindows/CVI, y ou m us t choos e yo ur co mpat ibl e co mpil er. If y ou w a nt
to change your choice of compatible compiler later, you can run the installation program and
change to another compatible compiler.
You can see which compatible compiler is active in LabWindows/CVI by selecting the
Compiler Options command in the Options menu of the Project window.
Object Files, Library Files, and DLL Import Libraries
If you create an object f i le, l ibrary file, or DLL import li br ary in LabWindows/CVI, you can
use the file only in the current compatible compiler or in a copy of LabWindows/CVI
that you installed with the same comp atibility choice. For detailed information on using
LabWindows/CVI-generated object and static library files in external compilers, refer to
the Using LabWindows/CVI Libr aries in External Compilers section later in thi s chap ter.
If you load an object file, library file, or DLL import library file in LabWindows/CVI,
you must have created the file in the current compatible compiler or in a copy of
LabWindows/CVI that you installed with the same compatibility choice. If you have
a DLL but you do not have a compatible DLL import library, LabWindows/CVI reports an
error when you attempt to link your project.
To create a compatible import library, you must have an include file that contains the
declarations of all the functions and global variables you want to access from the DLL.
Load the include file into a Source window, and select the Generate DLL Import Library
command in the Options menu.
Make sure the calling conventions of the function declarations in the include file match the
calling convention of the functio ns in the DLL. Whereas DLLs usually export functions with
__stdcall calling convention, the __stdcall keyw ord is somet imes mi ssing from t he
the
function declarations in the associated include files. If you generate an imp ort library from an
include file that does not agree with the calling convention the DLL uses, you can successfully
build a project that contains the import library, but LabWindows/CVI usually reports a general
protection fault when you run the project.
Compatibility Issues in DLLs
In general, you can use a DLL without regard to the compiler you used to create it. Only the
DLL import library must be created for the current compatible compiler. Some cases exist,
however, in which you cannot call a DLL that you created using one compiler from an
executable or DLL that you created using another compiler. If you want to create DLLs that
you can use in different compilers, design the Application Programming Interface (API) for
your DLL to avoid such problems. The following are areas in which the DLLs that external
compilers create are not fully compatible.
National Instruments Corporation3-5LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
Structure Packing
The compilers differ in their default maximum alignment of elements within structures.
If your DLL API uses structures, you can guarantee compatibility among the different
compilers by using the
this pragma in the DLL include file, before the definitions of the structures. You can choose
any alignment factor . After the structure definitions, reset the maximum alignment factor back
to the default, as in the following example:
#pragma pack (4) /* set maximum alignment to 4 */
typedef struct {
char a;
int b;
} MyStruct1;
typdef struct {
char a;
double b;
} MyStruct2;
pack pragma to specify a specific maximum alignment factor. Place
#pragma pack () /* reset max alignment to default */
LabWindows/CVI predefines the __DEFALIGN macro to the default structure alignment of
the current compatible compiler.
Bit Fields
Borland C/C++ uses the smallest number of bytes necessary to hold the bit f ields you specify
in a structure. The other compilers always use 4-byte elements. You can force compatibility
by adding a dummy bit field of the correct size to pad the set of contiguous bit fields so that
they fit exactly into a 4-byte element. Example:
typedef struct {
int a:1;
int b:1;
int c:1;
int dummy:29; /* pad to 32 bits */
} MyStruct;
The compilers return float and double scalar values using different mechanisms. This is
true of all calling conventions, including
to change your DLL API so that it uses output parameters instead of return values for
float scalars.
and
__stdcall. The only solution for this problem is
double
Returning Structures
For functions you do not declare with the __stdcall calling convention, the compilers
return structures using diffe rent mechanisms. For functions you declar e with
compilers return structures in the same way, except for 8-byte structures. National
Instruments recommends that your DLL API use structure output parameters instead of
structure return values.
__stdcall, the
Enum Sizes
By default, Watcom uses the smallest integer size necessary to represent the largest enum
value: 1 byte, 2 bytes, or 4 bytes. The other compilers always use 4 bytes. Force compatibility
by using the
-ei (Force Enums to Type Int) option with the Watcom compiler.
Long Doubles
In Borland C/C++, long double values are 10 bytes. In the other compilers, the y are 8 bytes.
In LabWin dows/CVI, they are al ways 8 bytes. Avoid using
long double in your DLL API.
Differences between LabWindows/CVI and the External Compilers
LabWindows/CVI does not work with all the non-ANSI extensions each external compiler
provides. Also, in cases where ANSI does not specify the exact implementation,
LabWindows/CVI does not always agree with the external compilers. Most of these
differences are obscure and rarely encountered. The following are the most important
differences you might encounter:
wchart_t is only one-byte in LabWindows/CVI.
•
•64-bit integers do not exist in LabWindows/CVI.
•
long double values are 10 bytes in Borland C/C++ but 8 bytes in LabWindows/CVI.
•You cannot use structured exception handling in La bWindows/CV I.
•Y ou cannot use the W atcom C/C++ __
functions that return
is not the default calling convention.
•LabWindows/CVI does not define
__SC__. The external compilers each define one of these macros. If you port code
National Instruments Corporation3-7LabWindows/CVI Programmer Reference Manual
float or double scalar values or structures. In Watcom, __cdecl
cdecl calling convention in LabWindows/CVI for
_MSC_VER, __BORLANDC__, __WATCOMC__, and
Chapter 3Windows 95/NT Compiler/Linker Issues
originally developed under one of these external compilers to LabWindows/CVI, you
might have to manually define one of these macros.
External Compiler Versions Supported
The following versions of each external compiler work with LabWindows/CVI for
Windows 95/NT:
•Microsoft Visual C/C++, version 2.2 or higher
•Borland C/C++, version 4.51 or higher
•Watcom C/C++, version 10.5 or higher
•Symantec C/C++, version 7.2 or higher
Required Preprocessor Definitions
When you use an external compiler to compile source code that includes any of the
LabWindows/CVI include files, add the following to your preprocessor definitions:
_NI_mswin32_
Multithreading and the LabWindows/CVI Libraries
Although the LabWindows/CVI environment is not multithreaded, you can use
LabWindows/CVI Libraries in the following multithreaded contexts:
•When you call the LabWindows/CVI Libraries from a multithreaded executable you
create in LabWindows/CVI or in an external compiler.
•When you call the LabWindows/CVI Libraries from a DLL that a multithreaded
executable loads. You can create the DLL in LabWindows/CVI or in an external
compiler.
•When you call the LabWindows/CVI Libraries from an object or static library file that
you dynamically load in a multithreaded e x ecutable. You can create the object or library
file in LabWindows/CVI or in an external compiler.
All the LabWindows/CVI libraries are multithreaded safe when used outside of the
LabWindows/CVI development environment.
For detailed information on how to use the LabWindows/CVI User Interface Library in a
multithreaded program, refer to Chapter 3, Programming with the User Interface Library , in
the LabWindows/CVI User Interface Reference Manual.
Using LabWindows/CVI Libraries in External Compilers
Under Windows 95/NT, you can use the LabWindows/CVI libraries in any of the four
compatible external compilers. You can create executables and DLLs that call the
LabWindows/CVI libraries. LabWindows/CVI ships with the run-time DLLs that contain all
the libraries. Executable files you create in LabWindows/CVI also use these DLLs. The
cvi\extlib directory contains DLL import libraries and a startup library, all compatible
with your external compiler. Nev er use the
compiler.
You must always include the following two libraries in your external compiler project:
National Instruments Corporation3-9LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
If you use an external compiler that requires a WinMain entry point, the following optional
library allows you to define only
cviwmain.lib /* contains a WinMain() function which */
/* calls main() */
main in your program.
Include Files for the ANSI C Library and the LabWindows/CVI Libraries
The cvirt.lib import library contains symbols for all the LabWindows/CVI libraries,
except the ANSI C standard library. When you create an executable or DLL in an external
compiler, you use the compiler’s o wn ANSI C standard library . Because of this, you must use
the external compiler’s include files for the ANSI C library when compiling source files.
Although the include files for the other LabWindows/CVI libraries are in the
directory, the LabWindows/CVI ANSI C include files are in the
directory. Thus, you can specify
cvi\include as an include path in your ex ternal co mpiler
cvi\include\ansi
while at the same time using the external compiler’s version of the ANSI C include files.
cvi\include
Note
Use the external compiler’s ANSI C include files only when you compile a source
file that you intend to link using the external compiler. If you intend to link the file
in LabWindows/CVI, use the LabWindows/CVI ANSI C include files. This is true
regardless of which compiler you use to compile the source file.
For more information, refer to the Setting Up Include Paths for LabWindows/CVI, ANSI C,
and SDK Libraries section later in this chapter.
Standard Input/Output Window
One effect of using the external compiler’s ANSI C standard library is that the printf and
scanf functions do not use the LabWindows/CVI Standard Input/Output window. If you
want to use
printf and scanf, you must create a console application, which is called a
character-mode executable in Watcom.
You can continue to use the LabWindows/CVI Standard Input/Output Window by calling the
FmtOut and ScanIn functions in the Formatting and I/O library.
Resolving Callback References from .UIR Files
When you link your program in LabWindows/CVI, LabWindows/CVI keeps a table of the
non-static functions that are in your project. When your program calls
LoadMenuBar, the LabWindows/CVI User Interface Library uses this table to find the
callback functions associated with the objects you load from the user interface resource
.uir) file. This is true whether y ou run your p rogram in t he LabW indo ws/CVI de vel opment
When you link your program in an external compiler, the external compiler does not make
such a table available to the User Interface Library. To resolve callback ref erences, you must
use LabWindows/CVI to generate an object file that contains the necessary table.
1.Create a LabWindows/CVI project that contains the
.uir files your program uses, if you
do not already have one.
2.Select the External Compiler Support command in the Build menu of the Project
window. A dialog box appears.
3.In the UIR Callbacks Object File control, enter the p athname of the object file yo u wan t
to generate. When you click on the Create button, LabWindows/CVI generates the
object file with a table that contains the names of all the callback functions referenced in
.uir files in the project. When you modify and save any of these .uir files,
all the
LabWindows/CVI regenerates the object file to reflect the changes.
4.Include this object file in the external compiler project you use to create the executable.
5.You must call
InitCVIRTE at the beginning of your main or WinMain function. Refer
to the Calling InitCVIRTE and CloseCVIRTE section later in this chapter.
Linking to Callback Functions Not Exported from a DLL
Normally, the User Interface Library searches for callback functions only in the table of
functions in the executable. When you load a panel or menu bar from a DLL, you might want
to link to non-static callback functions the DLL contains, but does not export. You can do this
by calling
LoadPanelEx and LoadMenuBarEx, the User Interface Library searches the table of
callback functions the DLL contains before searching the table that the executable contains.
Refer to Chapter 4, User Interface Librar y Function Reference, of the LabWindow s/CVI User Interface Reference Manual for detailed information on
LoadMenuBarEx.
LoadPanelEx and LoadMenuBarEx. When you pass the DLL module handle to
LoadPanelEx and
If you create your DLL in LabWindows/CVI, LabWindows/CVI includes the table of
functions in the DLL automatically. If you create your DLL using an external compiler, you
must generate an object file that contains the necessary table as follows.
1.Create a LabWindows/CVI project that contains the
.uir files your DLL loads, if you
do not already have one.
2.Select the External Compiler Support command in the Build menu of the Project
window. A dialog box appears.
3.In the UIR Callbacks Object File control, enter the p athname of the object file yo u wan t
to generate. When you click on the Create button, LabWindows/CVI generates the
object file with a table that contains the names of all the callback functions referenced in
.uir files in the project. When you modify and save any of these .uir files,
all the
LabWindows/CVI regenerates the object file to reflect the changes.
National Instruments Corporation3-11LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
4.Include this object file in the external compiler project you use to create the DLL.
5.You must call
InitCVIRTE and CloseCVIRTE in your DLLMain function. Refer to the
Calling InitCVIRTE and CloseCVIRTE section later in this chapter.
Resolving References from Modules Loaded at Run-Time
Note
This section does not apply unless you us e LoadExternalModule to load object
or static library files.
Unlike DLLs, object and static library files can contain unresolved references. If you call
LoadExternalModule to load an object or static library file at run time, the Utility
Library must resolve those references using function and variable symbols from the
LabWindows/CVI Run-time Engine, from the executable, or from previously loaded run-time
modules. A table of these symbols must be available in the executable. When you link your
program in LabW indows/CVI, LabW indows/C VI automatically includes a symbol t able. This
is true whether you run your program in the LabW in dows/CVI dev e lo pmen t environmen t or
as a standalone executable.
When you link your program in an external compiler, the external compiler does not make
such a table available to the Utility Library. LabWindows/CVI provides ways to help you
create the symbol table easily.
Resolving References to the LabWindows/CVI Run-Time Engine
LabWindows/CVI makes available two object files that contain symbol table information for
the LabWindows/CVI libraries that are in Run-time Engine DLLs:
•Include
modules refer to any symbols in the User Interface, Formatting and I/O, RS-232, DDE,
TCP, or Utility Library.
•Include
modules refer to any symbols in the ANSI C library . If you ha ve to use thi s object fil e and
you use Borland C/C++ to create your executable, you must choose Static Linking for the
Standard Libraries. In the Borland C/C++ IDE, you can do this in the New Target and
Target Expert dialog boxes.
cvi\extlib\refsym.obj in your external compiler project if your run-time
cvi\extlib\arefsym.obj in your external compil er project if your run- time
Resolving References to Symbols Not in Run-Time Engine
If your run-time modules refer to any other symbols from your executable, you must use
LabWindows/CVI to generate an object f ile that contains a table of those symbo ls. Create an
include file that contains complete declarations of all the symbols your run-time mo dules
reference from the executable. The include f ile can contain nested
can contain executable symbols that your run-time modules do not refer to. If your run-time
module references any of the commonly used Windows SDK functions, you can use the
cvi\sdk\include\basicsdk.h file.
Execute the External Compiler Support command in the Build menu of the Project window .
A dialog box appears. Enable the Using Load External Module option. Enable the Other
Symbols checkbox if it is not already enabled. Enter the pathname of the include file in the
Header File control. Enter the pathname of the object file to generate in the Object File
control. Click on the Create button to the right of the Object File control.
Include the object file in the external compiler project you use to c reate your executable. Also,
you must call
InitCVIRTE at the beginning of your main or WinMain function. Refer to the
Calling InitCVIRTE and CloseCVIRTE section later in this chapter.
Resolving Run-Time Module References to Symbols Not Exported
from a DLL
When you load an object or static library file from a DLL, you might want to resolve
references from that module using global symbols the DLL contains, but does not export. You
can do this by calling
LoadExternalModuleEx, the Utility Library searches the symbol table the DLL contains
before searching the table that the executab le contains. Refer to Chapter 8, Utility Library, of
the LabWindows/CVI Standard Libraries Reference Manual for detailed information on
LoadExternalModuleEx.
LoadExternalModuleEx. When you pa ss th e DLL modu le h andle to
If you create your DLL in LabWin dows/CVI, LabW indows/C VI includes the ta ble of symbols
in the DLL automatically. If you create your DLL using an external compiler, the external
compiler does not make such a table available to the Utility Library. Thus, when you use an
external compiler, you must include in your DLL one or more object files that contain the
necessary symbol tables. You can do this using the technique that the previous section,
Resolving References to Symbols Not in Run-Time Engine, describes. You must call
InitCVIRTE and CloseCVIRTE in your DLLMain functio n. Refer to the Calling InitCVIRTE
and CloseCVIRTE section later in this chapter.
Run State Change Callbacks Are Not Available in External Compilers
When you use a compiled module in LabWindows/CVI, you can arrange for
LabWindows/CVI to notify the module of a ch ange in the e xecution status such as start, stop,
suspend, or resume. You do this through a callback function that is always named
__RunStateChangeCallback. The Notification of Changes in Run State section, in
Chapter 2, Using Loadable Compiled Modules, of this manual, describes this in detail.
The run state change callback capability in LabWindows/CVI is necessary because the
LabWindows/CVI development environment executes your program as part of the
LabWindows/CVI process. When your program terminates, the operating system does not
release resources as it does when a process terminates. LabWindo ws/CVI attempts to release
National Instruments Corporation3-13LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
resources your prog ram allocated, but yo ur compiled m odule mi ght ha ve t o do more. Also , if
the program suspends for de bugging purposes , you r compi le d module mi gh t have to disable
interrup ts.
When you run an executable created in an e xternal compiler, it always ex ecutes as a separate
process, even when you debug it. Thus, the run state change callback facility is not necessary
and does not work. External compilers report link errors when you define
__RunStateChangeCallback in more than one object file. If you include a run state
change callback in a compiled module that you intend to use both in LabWindows/CVI and
an external compiler , it is a good idea to put the callback function in a separate source file and
create a
.lib file instead of a .obj file.
Calling InitCVIRTE and CloseCVIRTE
If you link an executable or DLL in an external compiler, you must call the InitCVIRTE
function at the beginning of your
main, WinMain, or DLLMain function.
For an executable using
main as the entry point, your code must include the following
segment:
#include <cvirte.h>
int main (argc, char *argv[])
{
if (InitCVIRTE(0, argv, 0) == 0)
return (-1);/* out of memory */
/* your other code */
}
For an executable using WinMain as the entry point, your code must include the following
segment:
#include <cvirte.h>
int __stdcall WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
For a DLL, you also have to call CloseCVIRTE in DLLMain. The code must include the
following segment:
#include <cvirte.h>
int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID pvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
if (InitCVIRTE (hinstDLL, 0, 0) == 0)
return 0; /* out of memory */
/* your other ATTACH code */
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
/* your other DETACH code */
CloseCVIRTE ();
}
return 1;
}
Note
It is harmless, but unnecessary, to call these functions when you link your
executable in LabWindows/CVI for Windows 95/NT.
Watcom Stack Based Calling Convention
When you use the LabWindows/CVI libraries in the Watcom compiler, you must set the
default calling conv ention to the 8 0486 Stack Based calling convention. In the command line
compiler, this is the
-4s option. In the W atcom IDE, you can set the default calling convention
by using the Options»C Compiler Switches command. The option is in the T arget Processor
section of the Memory Model and P rocessor Switches section of the dialog box. If you do not
set this option, the Watcom linker reports undefined references to the LabWindows/CVI
run-time libraries.
Using Object and Library Files in External Compilers
When you use an external compiler to link a project that contains ob ject or static library f iles
created in LabWindows/CVI, keep several points in mind.
Default Library Directives
Most compilers insert default library directives in the object and library files they generate.
A default library directive tells the linker to automatically include a named library in the link.
Normally, the directive refers to the name of C library files. If no files in the link contain a
National Instruments Corporation3-15LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
default library directive, and the linker does not explicitly include a C library in the link, the
linker reports unresolved function references in the object modules.
Object and static library files that LabWindows/CVI creates do not contain a default library
directive. This has different implications for each compiler.
Microsoft Visual C/C++
If you include in your project at least one object file that contains a default library directive,
the Visual C linker uses that library to resolve references in all object and library files, even
the files you create in LabWindo ws/CVI. Object files you create in Visual C usually contain
default library directives.
If you do not include in your project any object files or libraries you create in Visual C, you
can add the following Visual C libraries to the project to avoid link errors:
libc.lib
oldnames.lib
In the V isual C development environment, add these library names using the Input category
in the Link tab of the Project Settings dialog box.
Borland C/C++
No problems exist with the absence of default library directives when you use the Borland
compiler.
Watcom C/C++
Like Visual C, at least one object file must contain a default library directive to cause the
C library to be linked in. In addition, Watcom also requires a default library directive for
floating-point support.
If you do not include in your project any object files with the required directives, add the
following libraries, in the order shown, to the Libraries setting in the Windows Linking
Switches dialog box:
clib3s
math387
noemu387
Symantec C/C++
Each object file must have the default library directive for the C library. You must explicitly
add the Symantec C library to your project. The library filename is
lib subdirectory under the Symantec installation directory.
When you link a Borland C/C++ project that contains object or static library files you create
in LabWindo ws/CVI, it is a good idea to configure the Borland project to use the static version
of the Borland C libraries.
If you choose to use the dynamic C libraries, you must compile the LabWindows/CVI object
modules with the
before including any of the Borland C header files.
_RTLDLL macro. You must define the _RTLDLL macro in your source code
Borland Incremental Linker
Y ou cannot use your LabWindo ws/CVI object or static library files in the Borland C compiler
if you choose to use the incremental linker. Turn off the Use Incremental Linker option.
Borland C++ Builder
You cannot use your LabWindows/CVI object or static library files in the
Borland C++ Bui lder.
Watcom Pull-in References
The W atcom linker does not automatically link the startup code into your application or DLL.
Instead, it requires the module that contains
special symbol that the appropriate startup code module resolves. The Watcom compiler
automatically generates a reference to the special symbol into any module that contains
WinMain, or DllMain. This symbol is __DLLstart_, _wstart2_, or _cstart_,
depending on whether the project is for a DLL, W indo ws application, or console app lication,
respectively. Object modules compiled in LabWindows/CVI do not contain such r eferences.
LabWindows/CVI cannot generate the correct reference because it makes no distinction
between console and non-console applications.
main, WinMain, or DllMain to reference a
Chapter 3Windows 95/NT Compiler/Linker Issues
main,
You must include the symbol reference in your object file explicitly. For example, if your
module contains the
the following to the source code for the module:
National Instruments Corporation3-17LabWindows/CVI Programmer Reference Manual
main function, you can generate the corr ect symbol reference b y addin g
Chapter 3Windows 95/NT Compiler/Linker Issues
Creating Object and Library Files in External Compilers
for Use in LabWindows/CVI
When you use a compatible external compiler to create an object or library file for
use in LabWindows/CVI, you must use the include files in the
cvi\sdk\include directories. Ensure that these directories have priority over the
default paths for the compiler’s C library and SDK library include files.
You must choose the compiler options carefully. LabWindows/CVI tries to work with the
default options for each compiler as much as possible. In some cases, however, you have to
choose options that override the defaults. In other cases you must accept the defaults.
Microsoft Visual C/C++
LabWindows/CVI is compatible with all the defaults.
You must not use the following options to override the default settings:
cvi\include and
/J
/Zp
/Ge
/Gh
/Gs
Borland C/C++
LabWindows/CVI is compatible with all the defaults.
You must not use the following options to override the default settings:
-a
-K
-u-
-N
-p
-pr
-fp
(Unsigned Characters)
(Struct Member Alignment)
(Stack Probes)
(Profiling)
(Stack Probes)
Certain specialized options can generate symbol references that cause link errors
in LabWindows/CVI. If you encounter a link error on a symbol in a module you
compiled in an external compiler and you do not recognize the symbol, try
changing your external compiler options.
National Instruments Corporation3-19LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
Creating Executables in LabWindows/CVI
Y ou can create true 32-bit W indows e xecutables in LabW indows/CVI fo r Windo ws 95/NT. In
LabWindo ws/CVI for Windo ws 3.1, you run standalone programs using a special e xecut able
file that contains the LabWindows/CVI run-time libraries.
at a time, Windows 3.1 loads extra copies of this special executable into memory. Under
Windows 95/NT, the LabWindows/CVI run-time libraries come in DLL form. Standalone
executables you create in LabW ind ows/CVI and e xecutables you create in external compilers
use the same DLLs. If you run more t han one pro gram at a time, Windows 95/NT lo ads only
one copy of the DLL.
To create a standalone executable, you must first select Standalone Executable fro m the
submenu attached to the Target command in the Build menu of the Project window. When
you select Standalone Executable, the Create Standalone Executable command appears
below the Target command in the Build menu. The Create Standalone Executable
command under Win dows 95/NT is the same as under Windows 3.1, except that you also can
specify version information to include in the executable in the form of a standard Windows
version resource.
If you run more than one program
Creating DLLs in LabWindows/CVI
In LabWindows/CVI for Windows 95/NT, you can create 32-bit DLLs. Along with each
DLL, LabWindows/CVI creates a DLL import library for your com patible compiler . You can
choose to create DLL import libraries compatible with all four external compilers.
You must have a separate project for each DLL you want to create. Select Dynamic Link Library from the submenu attached to the Target command in the Build menu of the Project
window. When you select Dynamic Link Library, the Create Dynamic Link Library
command appears below the Target command in the Build menu. Refer to Chapter 3, Project
Window , in the LabWindows/CVI User Manual, for detailed information on the Create
Dynamic Link Library command.
You can debug the DLLs you create in LabWindows/CVI. Refer to
(Windows 95/NT Only)
User Manual, for more information.
section in Chapter 3, Project Window, of the LabWindows/CVI
Customizing an Import Library
If you have to perform special processing in your DLL import library, you can customize it.
Instead of generating a
do this, however, you can export only functions from the DLL, not variables.
LabWindows/CVI Programmer Reference Manual3-20
.lib file, you can generate a .c f ile that contains source code. If you
To customize an import library, you must have an include file that contains the declarations
of all the functions you want to export from the DLL. Load the include file into a Source
window, and execute the Generate DLL Import Source command in the Options menu.
After you have generated the import source, you can modify it, including making calls to
functions in other source files. Create a new project that contains the import source file and
any other files it refers to. Select Static Library from the submenu attached to the Target
command in the Build menu of the Project window. Execute the Create Static Library
command.
NoteThis import source code does not operate in the same way as a normal DLL import
library. When you link a normal DLL import lib rary into an executable, the
operating system attempts to load the DLL as soon as the program starts. The
import source code LabWindows/CVI generates does not load th e DLL un til you
call one of the functions it exports.
Preparing Source Code for Use in a DLL
When you create a DLL, you must address the following issues that can affect your source
code and include file:
•The calling convention you use to declare the functions you want to export
•How you specify which DLL functions and variables you want to export
•Marking imported symbols in the DLL include file you distribute
This section discusses how you can address these issues when you create your DLL in
LabWindows/CVI. If you create your DLL in an external compiler, the approach is very
similar. The external compilers, however, do not agree in all aspects. This chapter also
discusses these differences.
Some of the information in this section is very technical an d complex. Recommend ations on
the best approaches to these issues are at the end of the section. These recommendations are
intended to make creating the DLL as simple as possible, and to make it easy to use the same
source code in LabWindows/CVI and the external compilers.
Calling Convention for Exported Functions
If you intend for only C or C++ programs to use your DLL, you can use the __cdecl or
Watcom stack-based calling convention to declare the functions you want to export. If,
however, you want your DLL to be callable from environments such as Microsoft Visual
Basic, you must declare the functions you want to export with the
convention.
You must do this by explicitly defining the functions with the _
true whether or not you choose to make _
National Instruments Corporation3-21LabWindows/CVI Programmer Reference Manual
_stdcall the default calling convention for your
__stdcall calling
_stdcall keyword. This is
Chapter 3Windows 95/NT Compiler/Linker Issues
project. You must use the __stdcall keyword in the declarations in the include file you
distribute with the DLL.
Other platforms, such as UNIX or Windows 3.1 do not recognize the
__stdcall keyword.
If you work with source code that you might us e on other platfo rms, you must use a macro in
place of
__stdcall. The cvidef.h include file defines the DLLSTDCALL macro for this
purpose.
The following are examples of using the
int DLLSTDCALL MyIntFunc (void);
char * DLLSTDCALL MyStringFunc (void);
Note
You cannot use the __stdcall calling convention on functions with a variabl e
DLLSTDCALL macro.
number of arguments. Consequently, you cannot use such functions in Microsoft
Visual Basic.
Exporting DLL Functions and Variables
When a program uses a DLL, it can access only the functions or variables that the DLL
exports. The DLL can expor t only globally declared functions and v ariables. The DLL cannot
export functions and variables you declare as
static.
If you create your DLL in LabW ind ows /CVI, you can i ndicate which f unctions and va riables
to export in two ways: the include file method and the qualifier method.
Include File Method
You can use include files to identify symbols to export. The include files must contain the
declarations of the symbols you want to export. The include files can contain nested
#include statements, but the DLL does not export the declarations in the nested include
files. In the Create Dynamic Link Library dialog box, you select from a list of all the include
files in the project.
The include file method does not work with other compilers. However, it is similar to the
.def method that the other compilers use.
Export Qualifier Method
You can mark each function and variable you want to export with an export qualifier.
Currently , not all compilers recognize the same e xpor t qualifier names. The most commonly
used qualifier is
LabWindows/CVI recognizes both. The
LabWindows/CVI Programmer Reference Manual3-22
__declspec(dllexport). Some also recognize __export.
macro to resolve diff erences among compilers a nd platform s. The f ollo wing are e xamples of
using the
int DLLEXPORT DLLSTDCALL MyFunc (int parm) {}
int DLLEXPORT myVar = 0;
DLLEXPORT macro:
If the type of your v ari able or f unction requir es an ast erisk ( *) in the syntax, put the qualifier
after the asterisk, as in the following example:
char * DLLEXPORT myVar = NULL;
NoteBorland C/C++ version 4.5x, requires that you place the qualifier before the
asterisk. In Borland C/C++ 5.0, you can place the qualifier on either side of the
asterisk.
When LabWindows/CVI creates a DLL, it exports all symbols for which export qualifiers
appear in either the definition or the declaration. If you use an export qualifier on the
definition and an import qualifier on the declaration, Lab Windows / CVI e x ports the symbol.
The external compilers differ widely in their behavior on this point. Some require that the
declaration and definition agree.
NoteIf you include in your DLL project an object or library file that defines exported
symbols, LabWindows/CVI cannot correctly create import libraries for each of the
external compilers. This problem does not arise if you use only source code files
in your DLL project.
Marking Imported Symbols in Include File Distributed with DLL
If your DLL might be used in a C or C++ environment, you must distribute an include file
with your DLL. The include f ile must declare all the symb ols the DLL ex ports. If an y of these
symbols are variables, you must mark them with an import qualifier. Variable declarations
require import qualifiers so that the compiler can generate the correct code for accessing the
variables.
You can use impo rt qualif iers on function d eclarations, but they are not necessary. When you
use an import qualifier on a function declaration, external compilers can generate slightly
more efficient code for calling the function.
Using import qualifiers in the include file you distribute with your DLL can cause problems
if you use the same include file in the DLL source code:
•If you mark variable declarations in the include file with import qualifiers and you use
the include file in a source file other than the one in which you define the variable,
LabWindows/CVI and the external compilers treat the variable as if it were imported
from another DLL and generate incorrect code as a result.
•If you use export qualifiers in the definition of symbols and the include file contains
import qualifiers on the same symbols, some external compilers report an error.
National Instruments Corporation3-23LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
You can solve these problems in several different ways:
•You can avoid exporting variables from DLLs, and thereby eliminate the need to use
import qualifiers. For each variable you want to export, you can create functions to
get and set its value or a function to return a pointer to the variable. You do not have
to use import qualifiers for functions. This is the simplest approach and works in
LabWindows/CVI. However, it does not work if you use an export qualifier in a
function definition and you create the DLL with an external compiler that requires
the declaration to use the same qualifier.
•You can create a separate include file for distribution with the DLL.
•You can use a special macro that resolves to either an import or export qualifier
depending on a conditional compilation flag. In LabWindows/CVI you can set the flag
in your DLL project by using the Compiler Defines command in the Options menu of
the Project window.
Recommendations
To make creating a DLL as simple as possible, adhere to the following recommendations:
•Use the
to export. Do not export functions with a variable number of arguments.
•Identify the symbols you w ant to export usi ng the include fi le method. Do not use e xport
qualifiers. If you use an external compiler, use the
•Do not export variables from the DLL. For each variable you want to export, create
functions to get and set its value or a function to return a pointer to the variable. Do not
use import qualifiers in the include file.
DLLSTDCALL macro in the declaration and definition of all functions you want
.def file method.
If you follow these recommendations, you reap the following benefits:
•Y ou can distribute with your DLL the same include file that you include in the source files
you use to make the DLL. This is especially useful when you create DLLs from
instrument drivers.
•You can use the same source code to create the DLL in LabW indo ws/CVI and an y of the
four compatible external compilers.
•You can use your DLL in Microsoft Visual Basic or other non-C environments.
Automatic Inclusion of Type Library Resource for Visual Basic
The Create Dynamic Link Library command gives you the option to automatically create
a Type Library resource and include it in the DLL. When you use this option, Visual Basic
users can call the DLL without having to use a header file that contains
for the DLL functions. The command requires that you have a function panel file for
your DLL.
If your function panel file contains help text, you can generate a Windows help file from it
using the Generate Windows Help command in the Options menu of the Function Tree
Editor window . The Create Dynamic Link Library command provides an option to include
links into the Window help file in the Type Library. These links allow Visual Basic users to
access the help information from the Type Library Browser.
Visual Basic has a more restricted set of types than C. Also, the Create Dynamic Link Library command imposes certain requirements on the declaration of the DLL API. Use the
following guidelines to ensure that Visual Basic can use your DLL:
•Always use typedefs for structure parameters and union parameters.
•Do not use enum parameters.
•Do not use structures that require forward references or that contain pointers.
•Do not use pointer types except for reference parameters.
Creating Static Libraries in LabWindows/CVI
You can create static library (.lib) files in LabWindows/CVI for Windows 95/NT. Static
libraries are libraries in the traditional sense—a collection of object files —as opposed to a
dynamic link library or an import library. You can use just one project to create static library
files that work with all four compatible external compilers, but only if you include no object
or library files in the project.
You must have a separate project for each static library you want to create. Select Static Library from the submenu attached to the Target command in the Build menu of the Project
window. When you select the Static Library option, the Create Static Library command
appears below the Target command in the Build menu. Refer to Chapter 4, Source,
Interactive Execution and Standard Input/Output Windows, of the LabWindows/CVI User
Manual for detailed information on the Create Static Library command.
Note
If you include a .lib file in a static library project, LabWindows/CVI includes all
object modules from the
.lib in the static library it creates. When you create an
executable or DLL, LabWindows/CVI uses only the necessary modules from the
.lib file.
Note
Do not set the default calling convention to __stdcall if you want to create a
static library for all four compatible external compilers.
National Instruments Corporation3-25LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
Creating Object Files in LabWindows/CVI
You can create an object file in LabWindows/CVI in one of two ways:
•Include a source (
source file by double-clicking in the space next to the filename in the Project window
under the column marked “O”. Compile the file.
•Open a source (
of the Source window.
In LabWindo ws/CVI for W indo ws 95/NT, you can choose to create an object file for only the
currently selected compiler or to create object files for all four compatible external compilers.
.c) file in your project. Enable the Compile into Object option for the
.c) file and select the Create Object File command in the Options menu
Note
Do not set the default calling convention to __stdcall if you want to create a
static object for all four compatible external compilers.
Calling Windows SDK Functions in LabWindows/CVI
You can call Windows SDK Functions in LabWindows/CVI for Windows 95/NT. If you
install the LabWindows/CVI full development system from CD-ROM, you can call all
the Windows SDK functions. Otherwise, you can call only a subset of the Windows SDK
functions.
To view help for the SDK functions, select the Windows SDK command in the Help menu
of any LabWindows/CVI window.
Windows SDK Include Files
You must include the SDK include files before the LabWindows/CVI include files. In this
way, you avoid problems that arise from function name and typedef conflicts between the
Windows SDK and the LabWindows/CVI libraries. The LabWindows/CVI include files
contain special macros and conditional compilation to adjust for declarations in the SDK
include files. Thus, LabWindows/CVI must process the SDK include files first, followed by
the LabWindows/CVI include files.
When you compile in LabWindows/CVI or when you use an external compiler to compile
your source files for linking in LabWindows/CVI, use the LabWindows/CVI SDK include
files. The LabW indows/CVI SDK include files are in the
LabWindows/CVI compiler automatically searches the
do not have to add it to your include paths.
cvi\sdk\include directory. The
cvi\sdk\include directory. You
When you use an external compiler to compile and link your source files, you must use the
SDK include files that come with the external compiler. If you use an external compiler to
compile your source files for linking in LabWindows/CVI, use the LabWindows/CVI SDK
include files. For more information, refer to the Setting Up Include Paths for
LabWindows/CVI, ANSI C, and SDK Libraries section later in this chapter.
The number of SDK include files is very large. Normally, you have to include only
windows.h because it includes many, b ut not all, of the other include files. The inclusion of
windows.h along with its subsidiary include files significantly increases compilation time
and memory usage.
compiling by elim in ating t he less commonly us ed por tions of
include files. By default, LabWindows/CVI adds
WIN32_LEAN_AND_MEAN is a macro from Microsoft that speeds
windows.h and its subsidiary
/DWIN32_LEAN_AND_MEAN as a
compile-time definition when you create a new project. Y ou can alter this setting by using the
Compiler Defines command in the Options menu of the Project window.
Using Windows SDK Functions for User Interface Capabilities
The LabWindows/CVI User Interface Library uses the Windows SDK. It is not designed to
be used in programs that attempt to build other user interface objects at the SDK level. While
no specific restrictions exist on using SDK functions in LabWindows/CVI, National
Instruments recommends that you base your user interface either entirely on the
LabWindows/CVI User Interface Library or entirely on another user interface development
system.
Using Windows SDK Functions to Create Multiple Threads
Although you can use the Windows SDK Functions to create multiple threads in a
LabWindows/CVI program, the LabWindows/C VI development environment cannot hand le
multiple threads. For instance, if your main program terminates without destroying the
threads, they do not terminate. Also, the LabWindows/CVI libraries are not multithread safe
when you run a program in the LabWindows/CVI development environment.
For information on using the LabWindows/CVI libraries in a multithreaded executable, refer
to the Multithreading and the LabWindows/CVI Libraries section earlier in this chapter.
Automatic Loading of SDK Import Libraries
All the SDK functions are in DLLs. LabWindows/CVI and the four external compilers each
come with a number of DLL import libraries for the SDK functions. Most of the commonly
used SDK functions are in the following three import libraries:
kernel32.lib
gdi32.lib
user32.lib
LabWindows/CVI for W indows 95/NT automatically loads these three libraries when it starts
up and searches them to resolv e references at link time. Th us, you do not ha ve to include these
libraries in your project.
National Instruments Corporation3-27LabWindows/CVI Programmer Reference Manual
Chapter 3Windows 95/NT Compiler/Linker Issues
If the LabW indows/C VI linker r eports SDK function s as unresolv ed references, y ou must add
import libraries to your project. Refer to the
of SDK import libraries to SDK functions. The import libraries are in the
directory.
cvi\sdk\sdkfuncs.txt file for associations
cvi\sdk\lib
Setting Up Include Paths for LabWindows/CVI, ANSI C,
and SDK Libraries
The rules for using SDK include files are not the same as the rules for using ANSI C standard
library include files, which in turn are different than the rules for using the LabWindows/CVI
library include files. Refer to the Include Files for the ANSI C Library and the
LabWindows/CVI Libraries and Windows SDK Include Files sections earlier in this chapter.
You must set up your include paths differently depending on the environment in which you
compile and link. A discussion of each case follows.
Compiling in LabWindows/CVI for Linking in LabWindows/CVI
Use the LabWindows/CVI SDK and ANSI C include files. You do not have to set up any
special include paths; LabWindows/CVI finds the correct include files automatically.
Compiling in LabWindows/CVI for Linking in an External Compiler
Use the LabWindows/CVI SDK include files and the ANSI C include files from the external
compiler. Using the Include Paths command in the Options menu of the Pr oject window , ad d
the following as explicit include paths at the beginning of the project-specific list:
cvi\include
cvi\sdk\include
directory containing the external compiler's ANSI C include paths
Compiling in an External Compiler for Linking in an External Compiler
Use the SDK and ANSI C include files from the external compiler. This happens
automatically. Specify the following directories as include paths in the external compiler for
the LabWindows/CVI library include files.
Compiling in an External Compiler for Linking in LabWindows/CVI
Use the LabWindows/CVI SDK and ANSI C include files. Specify the following directories
as include paths in the external compiler.
cvi\include
cvi\include\ansi
cvi\sdk\include
Handling Hardware Interrupts under Windows 95/NT
Under Windows 3.1, you can handle hardware interrupts in a DLL. Under Windows 95, you
must handle hardware interrupts in a VxD. Under Windows NT, you must handle hardware
interrupts in a kernel-mode driver. You cannot create VxDs and kernel-mode drivers in
LabWindows/CVI. Instead, you must create them in Microsoft Visual C/C++, and you also
must have the Microsoft Device Driver Developer Kit (DDK).
Under Windows 3.1, it is extremely difficult to call source code into LabWindows/CVI at
interrupt time. Making such a call is easier under Windows 9 5/NT. Under Windows 95/NT,
you can arrange for the VxD or kernel-mode driver to call a function in your
LabWindows/CVI source code after the interrupt service routine exits. Y ou do this by creating
a separate thread for your interrupt callback function. The callback function executes a loop
that blocks its thread until the interrupt service routine signals it. Each time the interrupt
service routine executes, it unblocks the callback thread. The callback thread then performs
its processing and blocks again.
LabWindows/CVI includ es source code template files for a VxD and a kernel mode driv er. It
also includes a sample main program to show you ho w to read and write registers on a boar d.
There is one se t of files for Windows 95 and anothe r for Windows NT.
The files are in
directory contains some basic information.
National Instruments Corporation3-29LabWindows/CVI Programmer Reference Manual
cvi\vxd\win95 and cvi\vxd\winnt. The file template.doc in each
Windows 3.1
Compiler/Linker Issues
This chapter describes the different kinds of compiled modules available under
LabWindows/CVI for Windows 3.1 and includes programming guidelines for
modules you generate with external compilers.
Using Modules Compiled by LabWindows/CVI
Y o u can generate a compiled .obj or .o module fr om a source f ile within LabW in dows/ CVI
using the Create Object File command in the Options menu of a Source window. You can
then use the compiled module in any of the methods described in the About Lo ada bl e
Compiled Modules section in Chapter 2, Using Loadable Compil ed Modules, of this manual.
Using 32-Bit Watcom Compiled Modules
under Windows 3.1
4
You must adhere to the following rules for a 32-bit Watcom compiled module (.obj or
.lib file):
•You can call LabWindows/CVI library functions.
•If you make a call to the ANSI C Standard Library, you must include the
LabWindows/CVI header files instead of the Watcom header files.
•You cannot call Watcom C library functions outside the scope of the ANSI C Standard
Library.
•You can call
lowlvlio.h from LabWindows/CVI.
•You cannot call functions in the Windows Software Development Kit (SDK), install
interrupts, perform DMA, or access hardware directly. These tasks must be done with a
Dynamic Link Library (DLL). The ex ception to this is that you can use the
functions.
•You cannot define a function as
from source code in LabW indo ws/CVI. Als o, you cannot u se any n on-ANSI-C-stand ard
National Instruments Corporation4-1LabWindows/CVI Programmer Reference Manual
open, close, read, write, lseek, or eof, but you must include
inp and outp
PASCAL, pascal, or _pascal if you intend to call it
Chapter 4Windows 3.1 Compiler/Linker Issues
keywords su ch as far, near, or huge in the declaration of functions to be called from
LabWindows/CVI source code.
•If your Watcom-compiled module performs floating point operations, you must use
Watcom Version 9.5 or later.
•Use the following options when you compile with Watcom IDE:
–Set the Project Target Environment to 32-bit Windows 3.x, and set the Image Type
to Library [.lib].
–Turn on the Disable Stack Depth Checkin g [-s] option.
–Turn on the Change Char Default to Signed [-j] option.
–Add
–Turn on the Generate as Needed [-of] option for Stack Frames.
–Turn on the No Debugging Information option.
–Turn on the In-line with Coprocessor [fpi87] option for Floating Point Model.
–Turn on the Compiler default option for the Memory Model.
–Turn on the 80486 Stack-Based Calling [-4s] option for the Target Processor.
•Use the following compiler flags when using
–
–You can use optimization flags in addition to the f, and you can use other flags, such
-zw -d_NI_mswin16_ to the Other Options.
-zw -s -4s -j -fpi87 -d0 -of -d_NI_mswin16_
-wn, which do not affect the generation of object code.
as
wcc386 or wcc386p:
Using 32-Bit Borland or Symantec Compiled Modules
under Windows 3.1
In this section, CVI refers to both LabWindows/CVI and Watcom modules, while Borland
applies to both Borland and Symantec modules.
The following restrictions apply to Borland object modules:
•Borland packs bit fields in structu res differently than CVI, so you cannot share structures
with bit fields betwe en Borland and CVI.
•Borland returns structures, floats, and doubles dif ferently than CVI. Therefore, functions
that return these types cannot be called from CVI if they are defined in Borland, or vice
versa. The exceptions are the ANSI C library functions that return doubles, which you
can call from within Borland compiled modul e s.
Note
LabWindows/CVI Programmer Reference Manual4-2
This rule applies only to return values. You can use structs, floats and doubles as
output parameters without limitation.
•ANSI C library functions div and ldiv return structures, and hence you cannot call
them from Borland compiled modules.
•The type
long double is the same as double in CVI, while in Borland it is 10 bytes
long, so you cannot share objects of this type between Borland and CVI modules. This
affects the
scanf, sscanf, fscanf, and others.
"%Le", "%Lf", "%Lg" format specifiers of printf, sprintf, fprintf,
•Because you cannot share structures with bit f ields between Borland and CVI, you cann ot
use the macros in
•
wchar_t is defined as a char in CVI, whereas it is defined as a short in Bo rland,
so ANSI C library functions that return
stdio.h (getc, putc, fgetc, fputc) in Borland objects.
wchar_t or take wchar_t parameters do
not work.
Use the following options when you compile with Bo rland C 4.x:
•Set the target to be a Win32 application.
•Define
•Set the include directories to point to
_NI_mswin16_.
cvi\include before other include directories.
•Turn off the Allocate Enums as Ints option.
•Turn off the Fast Floating Point option.
•Use the C calling convention.
If you use a file with a
file has a
extern "C" for any functions or variables you want to access from a C file.
.cpp extension, Borland C++ 4.x compiles it as a C++ source file; you must use
.c extension, Borland C++ 4.x compiles it as a C source file. If your
Use the following options when you compile with Sy mantec C++ 6.0:
•Set the target to be a Win32s executable.
•Define
_NI_mswin16_.
•Set the include directories to point to cvi\include before any other include directories.
•Set Structure Alignment to 1 byte.
•Turn off the Use Pascal Calling Convention option.
16-Bit Windows DLLs
You can call functions in a 16-bit DLL from source code or from a 32-bit compiled modu le.
You can compile your 16-bit DLL in any language using any compiler that generates DLLs.
If you want to program with DMA or interrupts, or access the W i ndo ws API, you must use a
Windows DLL.
National Instruments Corporation4-3LabWindows/CVI Programmer Reference Manual
Chapter 4Windows 3.1 Compiler/Linker Issues
You must observe certain rules and restrictions in a DLL you want to use with
LabWindows/CVI. If you experience problems using a DLL in LabWindows/CVI,
you might have to contact the developer of the DLL to obtain modifications.
Because LabWindows/CVI is a 32-bit application, special glue code is required to
communicate with a 16-bit DLL. For some DLLs, LabWindows/CVI can automatically
generate this glue code from the include file when loading the DLL. For other DLLs, you
have to modify the glue source code and compile it with Watcom into a
The normal way of communicating with a DLL is by calling fun ctions in the DLL. However,
cases exist where you must use other communication methods. The most typical case is that
of an interrupt service routine in a DLL that notifies the application when an interrupt occurs.
This is done through a callback function. Also, LabWindows/CVI can recognize messages
posted by a DLL through the Windows Application Programming Interface (API) function
PostMessage and initiate a callback function.
Helpful LabWindows/CVI Options for Working with DLLs
LabWindows/CVI provides two options that can be helpful when working with DLLs. The
options can be found in the Run Options menu of the Project window:
•Enable the Check Disk Dates Before Each Run option when you iteratively modify a
DLL or DLL glue code file and run a LabWindows/CVI test program that calls into the
DLL. By enabling the Check Disk Dates Before Each Run option, you ensure that you
link the most recent version of the DLL and DLL glue code into your pro gram . You can
leave this option enabled at all times. The only penalty is a small delay each time you
build or run the project.
•By default, LabW indows/CVI does not unload and relo ad DLLs between each execution
of your program. This eliminates the delay in reloading the DLLs b efore each run. It
allows the DLLs to retain state information between each run. If, ho wever , you use a DLL
that does not work correctly across multiple program executions, enable the Reload
DLLs Before Each Run option.
.obj or .lib file.
DLL Rules and Restrictions
T o call into a 16- bit DLL from LabW indows/CVI 3 2-bit code, you must obs erve the follo wing
rules and restrictions for DLL functions:
•In the DLL header file, change all references to
•In the DLL header file, change all references to
unsigned short.
•You can declare the functions in the DLL as
•You cannot use variable argument functions.
LabWindows/CVI Programmer Reference Manual4-4
int into references to short.
unsigned or unsigned int to
•You can use the ar g ument types char, unsigned char, int, unsigned int, short,
unsigned short, long, unsigned long, float, and double, as well as pointers to
any type, and arrays of any type. You can use typedefs for these types.
•You can use the return types
short, unsigned short, long, and unsigned long, as well as pointers to any type.
void, char, unsigned char, int, unsigned int,
You can use typedefs for these types.
•You can use the return types float and double only if the DLL is created with a
Microsoft C compiler, and the functions returning floats or double are declared with the
cdecl calling convention. You do not have to modify the glue code generated for
functions that return float or double values.
•In the DLL header file, enum sizes must be consistent between LabW indows/CVI and the
compiler for the DLL.
The size of ErrorType is 2 bytes in Visual C++, whereas it is 1 byte in
LabWindows/CVI. To force LabWindows/CVI to treat
ErrorType as 2 bytes, add
another enum value explicitly initialized to a 2-byte value, such as the following.
ErrorType_Dummy = 32767
•If the DLL you are using perfo rms DMA on a buf fer you pas s to it, you mi ght experi ence
a problem. The DLL might attempt to lock the buf fer in memory by calling the Windows
SDK function
Watcom
Write the DLL so that if
GlobalPageLock. GlobalPageLock fails on buffers allocated with the
malloc function that LabWindows/CVI uses in 32-bit mode.
GlobalPageLock fails, the DLL attempts to lock the buffer
with the following code:
int DPMILock (void *buffer, unsigned long size)
{
DWORD base;
unsigned sel, offset;
union _REGS regs;
sel = SELECTOROF(buffer);
offset = OFFSETOF(buffer);
base = GetSelectorBase(sel);
base = base+offset;
After the DMA is complete, you must unlock the buffer . You can unlock the buffer using
DPMILock function, if you set regs.x.ax to 0x601, instead of 0x600.
the
•If you compile the DLL with the
/FPi is the default), the DLL uses the WIN87EM.DLL floating point emulator.
(
LabWindows/CVI does not use
following strategy in the DLL to prevent conflicts:
1.Structure the code so that all functions that perform any floating-point math have
known entry and e xit po ints. Ide a lly, spe cify a p ar ticula r set of expo rted entry
points as the only ways into the floating-point code.
2.Call the Windows SDK function
previous signal handler in a function pointer.
3.If the DLL has its own exception handler, call
signal handler.
4.Perform the floating-point math.
5.Upon exiting through one of the well-defined DLL exit points, call the Windows
SDK function
the DLL’s use of
typedef void (*LPFNSIGNALPROC) (int, int);
FPTerm to restore the previous exception hand ler and termina te
WIN87EM.DLL.
/FPi or /FPc switches or with no /FP switches
WIN87EM.DLL. If the DLL uses WIN87EM.DLL, use the
FPInit in each of these entry points. Store the
signal to register the DLL’s own
/* prototypes for functions in WIN87EM.d11 */
LPFNSIGNALPROC PASCAL_FPInit (void);
VOID PASCAL_FPTerm (LPFNSIGNALPROC);
void DllFunction (void)
{
LPFNSIGNALPROC OldFPHandler;
/* save the floating point state, and setup the*/
/* floating point exception handler for this DLL. */
OldFPHandler = _FPInit ();
signal ( SIGFPE, DLLsFPEHandler); /* optional*/
.
.
.
/* perform the computations*/
.
.
.
/* restore the floating point state*/
_FPTerm (OldFPHandler);
}
Note
If you use Microsoft C to build the DLL, you might get a linker error for an
undefined symbol
versions 7.00 and later. Include the following dummy function in your
DLL to fix this error. Also, when linking to the DLL, specify
as the first library to be linked.
void _acrtused2 (void)
{
}
DLL Glue Code
Because LabWindows/CVI is a 32-bit application, it does not use 16-bit import libraries or
import statements in module definition files. Instead, LabWindows/CVI uses 32-bit DLL glue
code. In some cases, it is sufficient to use glue code that LabWindows/CVI automatically
generates when it loads the DLL. However, you cannot use this method in the following
cases:
•The DLL requires special interface functions compiled outside of the DLL.
•You expect to pass arrays bigger than 64 K to functions in the DLL.
•You pass a pointer to a function in the DLL, and the DLL uses the pointer after the
function returns. For example, you pass an array to a function that starts an asynchronous
I/O operation. The function returns immediately , but the DLL continues to oper ate on the
array .
•Y ou pass a f unction pointer to the DLL, and the DLL calls the f unction later . For example,
the DLL makes a direct callback into 32-bit code.
•Y ou pass to the DLL a pointer that points to other pointers. Two examples of pointers that
point to other pointers are an array of pointers and a structure pointer with pointer
members.
•The DLL returns pointers as return values or through reference parameters.
•The DLL exports functions by ordinal value only.
_acrtused2. This error occurs only in Microsoft C
WIN87EM.LIB
If your DLL falls into any of these categories, refer to the DLLs That Canno t Use Glue Co de
Generated at Load T ime section of this chapter for details on how to proceed. Other wise, refer
to the DLLs That Can Use Glue Code Generated at Load Time section, also in this chapter.
National Instruments Corporation4-7LabWindows/CVI Programmer Reference Manual
Chapter 4Windows 3.1 Compiler/Linker Issues
DLLs That Can Use Glue Code Generated at Load Time
If your DLL can use glue code generated at load time, LabWindows/CVI automatically
generates the glue code based on the contents of the
it loads it.
.h file it associates with the DLL when
Any functions declared as
PASCAL in the .h file. LabWindows/CVI ignores the PASCAL keyword except when
PASCAL, pascal, or _pascal in the DLL should be declared as
generating the glue code.
Use only standard ANSI C keywords in the
exception to this rule.) For example, do not use
Note
You can create an object module that contains the glue code. If you do so,
.h file. (The keyword PASCAL is the only
far, near, or huge.
LabWindows/CVI can load the DLL faster because it does not have to regenerate
and recompile the glue code. To create the object module, load the
.h file into a
Source window and select Options»Generate DLL Glue Object. If the DLL
pathname is listed in the project, replace it with the object module file. If the DLL
is not listed in the project, but is associated with a
module is in the same directory as the
.fp file.
.fp file, make sure the object
DLLs That Cannot Use Glue Code Generated at Load Time
If your DLL cannot use glue code generated at load time, you must generate a glue code
source file from the DLL include file using the Generate DLL G lue S o ur ce command from
the Options menu of a Source window. You must then compile the glue code using the
Watcom compiler to create a
.obj or .lib file to be loaded with the DLL. If you also have
interface functions that must exist outside the DLL, you must combine them with the glue
code to form the
.obj or .lib file.
Loading a DLL That Cannot Use Glue Code Generated
at Load Time
If you have a 32-bit Watcom comp il ed .obj or .lib file that contains glue code for a DLL,
LabWindows/CVI must load the
x.dll and x.obj in your program, add x.obj to the project. Do not add x.dll to the
project. The
.obj or .lib file causes LabWindows/CVI to load the .dll.
.obj or .lib file first. For instance, if you want to use
.obj or .lib file must contain the glue code for the DLL. It is the presen ce of th e glue
The
code that indicates to LabWindows/CVI that a
When LabWindows/CVI loads the
first looks for the
.dll, LabWindows/CVI looks fo r it us ing t he standar d Win dows DLL sear ch algori thm.
the
LabWindows/CVI Programmer Reference Manual4-8
.dll in the same directory as the .obj or .lib file. If it cannot find
.obj or .lib file and finds that it contains glue code, it
Also, you can create a .pth file in the same directory as the .obj or .lib file with the same
base name. The
.pth file must contain a simple filen ame or a full path name of the DLL. If it
is a simple filename, LabWindows/CVI uses the standard Windows DLL search algorithm.
Rules for the DLL Include File Used to Generate Glue Source
You can generate the DLL glue source file by opening the .h file for the DLL in a Source
window and selecting Generat e DLL Glue Source fro m the Options menu. Th is command
prompts you for th e name of a
base name as the
.h file. You must modify this .c file as this section describes and compile
it using the Watcom compiler. Refer to the Using 32-Bit Watcom Compiled Modules
under Windows 3.1 section of this chapter for information on how to use the Watcom
compiler with LabWindows/CVI.
.h file. It puts the glue code in a .c file with the same path and
If any of the functions in the DLL are declared as
declare them as
ignores the
PASCAL in the .h file you use to generate the glue code. LabWindows/CVI
PASCAL keyword exce pt for the purposes of generating the glue code. The stub
function in the glue code is not declared as
PASCAL, pascal, or _pascal, you must
PASCAL. If you include this .h file in the glue
code, the Watcom compiler flags as an error the inconsistency between the declaration of the
function in the
.h file and the definition of the stub function. If you include it in other modules
you compile under Watcom, calls to the function erroneously compile as if the function were
PASCAL. You have two o ptions:
•Have two se parate
Use the one that does include the
•Use conditional compilation so that Watcom ignores the
.h files, one that includes the PASCAL keyword and one that does not.
PASCAL keyword to generate the glue code only.
PASCAL macro when it
compiles.
Only use standard ANSI C keywords in the
exception to this rule. For example, do not use
.h file. The keyword PASCAL is the only
far, near, or huge.
If the DLL Requires a Support Module outside the DLL
Support modules contain special interface functions that the DLL uses but that exist outside
of the DLL. If you are unsure whether the DLL requires a support module, try to build a
project in LabWindows/CVI with the DLL in the project list. If link errors exist in the form
of unresolved references, the DLL requires special interface functions. Get the source code
for the interface functions, add it to the glue code, and compile using the Watcom compiler.
If You Pass Arrays Bigger Than 64 K to the DLL
If you pass the DLL any arrays bigger than 64 K, you must modify the glue code source f ile.
For example, suppose you have a function in the DLL with the following prototype:
long WriteRealArray (double realArray[], long numElems);
National Instruments Corporation4-9LabWindows/CVI Programmer Reference Manual
Chapter 4Windows 3.1 Compiler/Linker Issues
In the glue code generated by LabWindows/CVI, there is a declaration of WriteRealArray
like that shown in the following example.
long WriteRealArray (double realArray[], long numElems)
{
long retval;
unsigned short cw387;
cw387 = Get387CW();
retval = (long)
InvokeIndirectFunction (__static_WriteRealArray, realArray,
Set387CW (cw387);
return retval;
}
numElems);
Note
The lines of code referencing cw387 are necessary only if the DLL function
performs floating point opera tions. They are innocuous and execute quickly, so
LabWindows/CVI adds them to the glue code automatically. If the DLL function
does not perform floating point operations, you can remove these lines.
realArray can be greater than 64 K, you must modify the interface routine as shown.
If
long WriteRealArray (double realArray[], long numElems)
{
long retval;
unsigned short cw387;
DWORD size;
DWORD alias;
You must also modify the call to GetIndirectFunctionHandle for WriteRealArray as
shown in the following code:
if (!(__static_WriteRealArray = GetIndirectFunctionHandle
(fp, INDIR_PTR, INDIR_WORD, INDIR_ENDLIST)))
by changing INDIR_PTR to INDIR_DWORD.
If the DLL Retains a Buffer after the Function Returns
(an Asynchronous Operation)
If the DLL retains a buffer after the function returns, you must modify the glue code source
file. Suppose two functions exist.
WriteRealArray, except that it returns before it completes writing the real array.
ClearAsyncWrite terminates the asynchronous I/O. The glue code interface functions for
WriteRealArrayAsync and ClearAsyncWrite should be modified to resemble the
following example.
static DWORD gAsyncWriteAlias, gAsyncWriteSize;
long WriteRealArrayAsync (double realArray[], long numElems)
{
long retval;
unsigned short cw387;
DWORD size;
DWORD alias;
You can terminate LabWindows/CVI programs in the middle of execution and then re-run
them. When you terminate the program, you should also terminate the asynchronous I/O. You
can arrange to be notified of changes in the run state by including a function with th e name
RunStateChangeCallback in the .obj or .lib file associated with the DLL. You can add
this function to the glue code file. Refer to the Notification of C ha nges in Run State section
of Chapter 2, Using Loadable Compiled Modules, of this manual for a complete description
of the run state change notification. In the examp le we have b een discussing, you shou ld add
the following code.
if (newState == kRunState_Stop)
ClearAsyncWrite ();
}
/* retval is error */
If the DLL Calls Directly Back into 32-Bit Code
If the DLL calls directly back into 32-bit code, you must modify the glue code source file.
You can call functions defined in 32-bit source code directly from a DLL. Although this
method is not as straightforward as Windows messaging, it is not subject to the latencies of
Window messaging. For more information about Windows messaging, refer to the
Recognizing Windows Messages Passed from a DLL section of this chapter.
Note
LabWindows/CVI Programmer Reference Manual4-12
If you need direct callbacks to occur at interrupt time because the latency of
Windows messaging is interfering with your application, contact Na tional
Instruments for assistance.
You cannot pass pointers to 32-bit functions directly into 16-bit DLLs. The Windows SDK
interface for this is very complex. Generate DLL Glue Source does not generate this code
for you. You must write your o wn glue code f or passing fu nction point ers to and fro m a DLL,
and add it to the file that Generate DLL Glue Source generates.
Suppose a DLL contains the following functions:
long (FAR*savedCallbackPtr) (long);
long FAR InstallCallback(long (FAR*callbackPtr) (long))
{
savedCallbackPtr = callbackPtr;
}
long InvokeCallback(long data)
{
return (*savedCallbackPtr)(data);
}
After you use the Generate DLL Glue Source command to generate the glu e code fo r these
functions, you must modify the code as follows.
NoteBecause direct callbacks must be declared far, and LabWindows/CVI cannot
compile
it to the DLL. This
far functions, you must declare a far function in the glue code and pass
far function calls the actual user function.
#undef MakeProcInstance /* Use version that does not*/
/* convert pointer. */
#undef FreeProcInstance /* Use version that does not*/
/* convert pointer. */
typedef struct { /* Holds resources required to register*/
/* the callback. */
int UserDefinedProcHandle;
CALLBACKPTR proc16;
FARPROC proc16Instance;
/* Define a 32-bit far callback whose address is passed to */
/* the DLL. It calls your function using function pointer */
/* stored in UsersCallback. */
DLLs return pointers that fall into the following two classes.
•Pointers to memory that LabW indows/CVI allocates, that you pass into the DLL, an d that
the DLL later returns
You must map these pointers back into normal 32-bit pointers that you can use in
LabWindows/CVI code. Use the function
•Pointers to memory that a DLL allocates
Because these pointers point to memory that is not in the LabWindo ws/CVI flat address
space, you cannot map them back into the normal 32-bit point ers that LabW indo ws/CVI
uses. You can access them in Watcom object code by first converting them to 32-bit far
pointers using the function
MK_FP32.
To access them in LabWindows/CVI source code you must copy the data into a buffer
you allocate in LabW ind o ws/C VI. Notice t hat you canno t pass 16- or 32- bit far poi nt ers
to LabWindows/CVI library functions, and that LabWindows/CVI does not provide
access to the Watcom string and memory buffer manipulation functions that take far
pointers as arguments. You must write the loops to copy the data.
National Instruments Corporation4-17LabWindows/CVI Programmer Reference Manual
Chapter 4Windows 3.1 Compiler/Linker Issues
If a DLL Receives a Pointer that Points to Other Pointers
Assume the following DLL functions:
int f(char *ptrs[]);
struct x {
char *name;
};
int g(struct x *ptr);
For the function f, the glue code that LabWindows/CVI generates converts the pointer to the
ptrs to a 16-bit far pointer when you pass it to the DLL function, but does not convert
array
the pointers inside the array
glue code that LabWindows/CVI generates converts the po inter to the structure (
the pointer inside the structure (
If your DLL has functions with these types of parameters, then your DLL cannot use glue
code automatically generated at load time. You can use the Generate DLL Glue Source
command to generate glue code and th en modify it in the following manner.
1.Before the call to
a.Save the hidden pointer in a local variable.
b.Replace the hidden pointer with a 16-bit alias by calling
2.After the call to
a.Free the 16-bit alias by calling
b.Restore the hidden pointer with the value you saved in step 1.
(ptrs[0], ptrs[1], ...). Similarly, for the function g, the
InvokeIndirectFunction,
InvokeIndirectFunction,
ptr), but not
name).
Alloc16BitAlias.
Free16BitAlias.
For the functions
f and g, the glue code that LabWindows/CVI generates looks like the
After you make the necessary changes, the code should appear as follows:
/* Assume NUM_ELEMENTS is the number of pointers in the input */
/* array. Assume ITEM_SIZE is the number of bytes pointed*/
/* to by each pointer. If you do not know ITEM_SIZE, but you*/
/* know that it is 64K or less, you can use 64K as ITEM_SIZE. */
int f(char **ptrs)
{
int retval;
unsigned short cw387;
int i;
char *savedPointers[NUM_ELEMENTS];
/* change the pointers to 16-bit far pointers */
for (i = 0 ; i < NUM_ELEMENTS; i++) {
savedPointers[i] = ptrs[i];
if (Alloc16BitAlias(ptrs[i], ITEM_SIZE, &ptrs[i]) == -1) {
/* failed to allocate an alias; restore */
/* pointers. */
while (i--)
If your DLL does not export its functions by name, but by ordinal number only, you must
modify the
the function as the second parameter, pass
where
number for the function
GetProcAddress f unction calls in the glue code. I nstead of pass ing the name of
OrdinalNumber
is the ordinal number for the function. For example, if the ordinal
InstallCallback is 5, change the glue code as follows.
>;
PASS_WORD_AS_POINTER(
OrdinalNumber
),
Generated Glue Code:
if (!(fp = GetProcAddress(DLLHandle,"InstallCallback")))
{
The normal way of communicating with a DLL is to call functions in the DLL. However,
cases exist where other communication methods are necessary. The most typical case is that
of an interrupt service routine in a DLL that must notify the application that the interrupt
occurred. In cases like this, you must communicate with the DLL thr ough a callback fun ction.
LabWindows/CVI recognizes messages posted by a DLL through the Windows SDK
function
for hardware interrupts, but it is subject to the latency associated with Windows messaging.
LabWindows/CVI uses
GetCVIWindowHandle to recognize Windows messages from a DLL. You can call these
functions from a module compiled in Watcom or from source code.
For complete information on these functions, refer to the function descriptions in Chapter 4,
User Interface Library Reference, of the LabWindows/CVI User Interface Reference Manual.
PostMessage, and can initiate a user callback function. This method is useful
RegisterWinMsgCallback, UnRegisterWinMsgCallback, and
To use these functions, call
RegisterWinMsgCallback and GetCVIWindowHandle. Pass
their return values, the message number and the window handle, to the DLL. When the DLL
sends a message, it calls
PostMessage with these values. When LabWindows/CVI receives
the message, it calls the callback function.
Note
LabWindows/CVI can receive the message only when it is processing events.
LabWindows/CVI processes events when it is waiting for user input. If the
program you run in LabWindows/CVI does not call
GetUserEvent, or scanf, or if it does not return from a User Interface Library
callback, events will not be processed. You can remedy this in the program by
periodically calling the User Interface Library function
Creating 16-bit DLLs with Microsoft Visual C++ 1.5
Be sure to consider the following issues or project options when you create a DLL with
Microsoft Visual C++ 1.5:
•Every function you call fr om out side the DLL must be
data segment into the DS register. The fun ction mu st load the DS register if you want to
use any non-local variables in a function.
•Use the large or huge memory model. The savings you gain by using smaller memory
models is not worth having to use the
far keyword throughout your code. This project
option is in Compiler»Memory Model»Segment Setup.
•You can make the compiler load the data segment into the DS register automatically by
using the SS!=DS, DS loaded on function entry project option in Compiler»Memory Model»Segment Setup.
•If you try to use the optimize entry code option (
Compiler»Windows»Prolog/Epilog»Generate Prolog/Epilog For, it conflicts with the
National Instruments Corporation4-21LabWindows/CVI Programmer Reference Manual
Chapter 4Windows 3.1 Compiler/Linker Issues
/Au option. Y ou can either not use this option by setting it to None, or insert __loadds
in front of every function you export from the DLL.
•You can mak e the compiler e x port a f unction b y insertin g
type and the function name, or b y addin g the funct ion name to the e xports sect ion of t he
.def file.
•If you add the fu nction name t o the exp orts s ection of the .
the name to all caps if you use the
underscore if you use the
CDECL calling convention.
PASCAL calling convention, or pre-append an
•Byte align structure members by choosing 1 B yte for the Options»Pr oj ect»Comp ile r»
Code Generation»Struct Member Byte Alignment.
Creating 16-bit DLLs with Borland C++
Consider the following issues or project options when you create a DLL with
Borland C++ 4.x:
•Every function you call fr om out side the DLL must be
data segment into the DS register. The fun ction mu st load the DS register if you want to
use any non-local variables in a function.
•Use the large or huge memory model. The savings you gain by using smaller memory
models is not worth having to use the
option is in 16-bit Compiler»Memory Model»Mixed Model Override.
•You can make the compiler load the data segment into the DS register by setting the
project option 16-bit Compiler»Memory Model»Assume SS E quals DS to Never, or
by inserting
_loadds in front of every function you export from the DLL.
•You can make the compiler export a function by inserting
type and the function name, ad ding t he fun ction n ame to the e xport s secti on of the
file, or setting the option 16-bit Compiler»Entry/Exit Code»Windows DLL, all functions exportable.
•If you add the funct ion name to the ex ports sectio n of the
the name to all caps if you use the
underscore if you use the
CDECL calling con vention. Also, set the Generate Underscores
option in Compiler»Compiler Output.
•Turn off the Allocate Enums as Ints option in Compiler»Code Generation.
•Set the Data Alignment options to Byte in 16-bit Compiler»Processor.
•Turn off the Case Sensitive Link and Case Sensitive Exports and Imports options in the
Linker»General.
•Do not use the L i nker Goodies optio ns in Linker»16-bit Linker.
LabWindows/CVI finds a DLL file in the following ways for Windows 3.1:
•If the
•If the
.dll file is associated with a .fp file, LabWindows/CVI uses the following search
precedence to find the DLL.
1.If a
.pth file with the same full path name as the .fp file is in the project,
LabWindows/CVI uses the standard Windows DLL search algorithm. The
file must contain the name o f the
contain an absolute path or a simple filename.
2.If a
.dll file with the same full path name as the .fp file is in the project,
LabWindows/CVI uses th e ab solute path of the
.dll file.
the
3.If a
.pth file with the same base name as the .fp file is in the same directory as
.fp file and a .lib or .obj file of the same base name does not exist in the
the
same directory, La bWindow s/CVI use s th e stan dar d Window s D LL s earc h
algorithm. The
mystuff.dll. It must not contain any directory names or slashes .
4.If a
5.If a
.dll file with the same base name as the .fp file is in the same directory as
.fp file, LabWindows/CVI loads the .dll file as long as no .lib, .obj,
the
.pth file of the same base name appears in the same directory.
or
.pth or .dll file does not appear in the same directory as the .fp file,
LabWindows/CVI uses th e stan dard Windo ws sear ch a lgor ithm to loo k for a
DLL with the same base name as the
name is in the
PATH environment variable, LabWindo ws/CVI finds it.
your
DLLs for VXIplug&play drivers are not in the same directory as the
directory that contains the DLL is listed in the
Step 5 makes it easier for you to use VXIplug&play instrument driver DLLs in
LabWindo ws /CVI for Windows 3.1.
.dll file is not associated with a .fp file, LabWindows/CVI uses the following
search precedence to find the DLL:
1.If a
.pth file is in the project list, LabWindows/CVI uses the standard Windows
DLL search algorithm. The
such as
2.If the
mystuff.dll. It must contain an absolute path or a simple filename.
.dll file is in the project list, then LabWindows/CVI uses the absolute
pathname to find the
Chapter 4Windows 3.1 Compiler/Linker Issues
.pth
.dll file, such as mystuff.dll. It must
.dll file in the p ro jec t to lo ad
.pth file must contain the name o f th e .dll file, such as
.fp file. Thus, if a DLL with the same base
windows or windows\system directory or a directory listed in
National Instruments Corporation4-23LabWindows/CVI Programmer Reference Manual
Chapter 4Windows 3.1 Compiler/Linker Issues
•If you call LoadExternalModule on the .dll file, then
–If you specify it with an absolute pathname, LabWindows/CVI loads that file.
–If you specify it with a relative pathname, LabWindows/CVI searches for the
file in the following places and order indicated.
1.In the project list.
2.In the directory in which the project file is located.
3.Among other modules already loa ded.
4.In the directories specified in the documentation for the Windows SDK
LoadLibrary function. In this case, the include file for the DLL must be in
the project or in one of the includ e paths y ou spec ify in the I nclude Paths
command in the Options menu of the Project window.
This chapter describes the kinds of compiled modules available under LabWindows/CVI for
UNIX and includes programming guidelines for modules you generate with external
compilers.
Calling Sun C Library Functions
You can call functions in the Sun Solaris C libraries from source code in LabWindows/CVI.
LabWindows/CVI automatically links your program to the following static libraries, located
/usr/lib directory, when you build the project.
in the
5
Solaris 1:
Solaris 2: libsocket.a, libnsl.a, libintl.a, libm.a, libc.a
When you create a standalone executable, LabWindows/CVI invokes the Sun Solaris link
editor (
libraries. By default, the Sun Solaris link editor uses the dynamic versions of the libraries.
LabWindows/CVI passes the following linking options to the Sun Solaris link editor:
Solaris 1:
Solaris 2: -lsocket -lnsl -lintl -lm -lthread -lc
In general, you can use the header files that Sun provides for these libraries in the
/usr/include directory . For the ANSI C functions, ho we ver , use the header files that come
with LabWindows/CVI.
libm.a, libc.a
ld) to link your program to the LabWindows/CVI dynamic library and to the system
-lm -ldl -lc
Restrictions on Calling Sun C Library Functions
You cannot call any Sun C Library function that uses data types incompatible with the
LabWindows/CVI compiler or libraries. In particular, you must not call functions that use the
long double data type. In LabWindows/CVI the long double data type has 8 bytes, but the
Sun libraries expect a 16-byte object.
Under Solaris 2, you must not call any function that uses the
LabWindows/CVI does not recognize this non-ANSI type.
National Instruments Corporation5-1LabWindows/CVI Programmer Reference Manual
Chapter 5UNIX Compiler/Linker Issues
Using Shared Libraries in LabWindows/CVI
In the LabWindows/CVI development environment, you can link your programs to static
libraries, but not to shared libraries. If you hav e to use a shared library, you must use the Sun
Solaris linker (
LabWindows/CVI Libraries section later in this chapter for more information on using
external compilers and the Sun linker.
If you have both shared and static versions of a library, you can develop and debug your
application in the LabWindows/CVI de velopment en vironment using the static version of the
library . You can then create your final executable with the Sun linker using the shared version
of the library.
Using dlopen
The Sun Solaris dlopen function allows you to load shared libraries from your program
dynamically. Although this function can work in some cases when running in
LabWindows/CVI, it can make LabWindows/CVI unstable. If you use
libraries in a program you run in LabWindows/CVI, the shared libraries might link to the
system libraries the LabWindows/CVI environment uses. As a result, functions in the shared
library might modify the LabWindows/CVI environment and cause unpredictable behavior.
ld) to build your application. Refer to the Creating Executables that Use the
dlopen to load shared
The LabWindows/CVI Run-Time Engine
as a Shared Library
The LabWindo ws/CVI dev elopment en vironment contains many b uilt-in libraries such as the
User Interface Library and Utility Library. LabWindows/CVI also provides these lib raries in
the form of a standalone shared library called the LabWindows/CVI Run-time Engine. All
executables that call LabWindows/CVI library functions use the Run-time Engine shared
library. This is true whether you build the executable in the LabWindows/CVI development
environment or with an external compiler and the Sun Solaris linker.
Creating Executables that Use the
LabWindows/CVI Libraries
You can build executables that use the LabWindows/CVI libraries in two ways:
•You can build an executable in the LabWindows/CVI development environment by
selecting the Create Standalone Executable command in the Build menu of the Project
window. When you do so, LabWindows/CVI invokes the Sun Solaris linker (
your programs to the Run-time Engine shared library.
•You can use an external compiler and linker to create an executable that uses the
Run-time Engine shared library. Use the Gen erate Makefile comman d in the Build menu
of the Project window to generate a UNIX makefile that corresponds to the currently
loaded project and libraries. The makefile invokes an external compiler to compile your
source files, and then it invokes the Sun Solaris linker (
the Run-time Engine shared library.
Compatible External Compilers
Y o u can use the following external ANSI C compilers to compile source files for linking with
the LabWindows/CVI Run-time Engine shared library.
•GNU C Compiler (
•Sun C Compiler (
gcc)
cc and acc)
Chapter 5UNIX Compiler/Linker Issues
ld) to link
ld) to link the compiled files with
Note
Under Solaris 2.4, when linking the LabWindows/CVI Shared Library with
external ANSI C compiler, the compiler displays a warning that states the shared
library has an invalid type. You can ignore this warning.
Static and Shared Versions of the ANSI C and Other Sun Libraries
When you build a project for execution in the LabWindows/CVI development environment,
LabWindows/CVI links your program to the static versions of the Sun Solaris libraries
libc.a and libm.a). On the other hand, when you create a standalone executable in the
(
LabWindows/CVI development environment, LabW indows/CVI invokes the Sun Solaris link
ld) to link your program to the shared versio ns of the librar ies (libc.so and
editor (
libm.so). Similarly, when you generate a UNIX makefile by invoking the Generate
Makefile command from the Build Menu of the Project window , the makef ile contains linker
commands to use the shared versions of the libraries.
Thus, when you run your programs as executables, you use a different version of the Sun
libraries (including the ANSI C library) than when you run them in the LabWindows/CVI
development environment. Your program might exhi bit slightly different behavior as a
standalone executable than when run in the development environment.
National Instruments Corporation5-3LabWindows/CVI Programmer Reference Manual
Chapter 5UNIX Compiler/Linker Issues
Non-ANSI Behavior of Sun Solaris 1 ANSI C Library
The C library that comes with Sun Solaris 1 (SunOS 4.1.x) does not comply with the ANSI C
standard as follows:
•Some ANSI C functions are missing from the library.
•Some library functions have different behavior than the ANSI standard specifies.
LabWindows/CVI corrects these problems by adding a library,
replaces and supplements the Sun Solaris library as necessary. The So lari s 1 ANS I C L ibrar y
Implementation section contains mor e inform ation abou t ho w LabWindo ws/CVI prov ides an
ANSI C library o n Solaris 1.
LabWindows/CVI Implements printf and scanf
Although the Sun Solaris libraries provide the ANSI C family of functions for formatted input
and output (
scanf, printf, and others), LabWindows/CVI provides special versions of
these functions for the following reasons:
•The LabWindows/CVI versions of these functions provide run-time error checking not
available with Sun Solaris versions.
•The Sun Solaris 1 version of these functions do not comply fully with the ANSI C
standard.
•The Sun Solaris versions of these functions do not work with the LabWindows/CVI
implementation of the long double data type.
For standalone executables, these functions come in a separate static library,
libcviprintf.a, in the lib subdirectory of the LabWindows/CVI installation directory.
When you create an ex ecutable in LabWindows/CVI, Lab Windows/CVI links you r p rog ram
to this static library.
Main Function Must Call InitCVIRTE
If your program calls any functions from the LabWindows/CVI libraries, you must call
InitCVIRTE to initialize the libraries from the executable. This function takes three
arguments. The first and third arguments to this function must always be 0 for UNIX
applications. The second must be the same value as the second parameter of your
function.
InitCVIRTE returns 0 if it fails.
libcfix.a, that
main
You do not have to call
InitCVIRTE when you run your program in the LabWindows/CVI
development environment because LabWindows/CVI always initializes the libraries.
However, if you do not call
LabWindows/CVI Programmer Reference Manual5-4
InitCVIRTE, your executable cannot work. For this reason,
National Instruments recommends that you always include source code similar to the
following example in your program.
int main(int argc, char *argv[])
{
if (InitCVIRTE(0, argv, 0) == 0) {
return 1;/* Failed to initialize */
}
/* your program code here */
}
If you pass NULL for the second argument to InitCVIRTE, your program might still work,
but with the following limitations:
•Your executable cannot accept the
-display command line argument. As a result, you
cannot specify an X display on the command line for your program to use. You still can
use the
•
LoadPanel, LoadExternalModule, DisplayImageFile, SavePanelState,
RecallPanelState, and other functions that normally use the directory of the
DISPLAY environment variable to specify a different X display.
executable to search for files, use the current working directory instead. If you run the
executable from a directory other than the one that contains your executable, some of
these functions might fail to find files.
Run State Change Callbacks Are Not Available in Executables
When you use a compiled module in LabWindows/CVI, you can arrange for
LabWindows/CVI to notify it of a change in execution status (start, stop, suspend, resume).
You do this through a function called
Changes in Run State section, in Chapter 2, Using Loadable Compiled Modules, describes
this in detail.
The run state change callback capability in LabWindo ws/CVI is necessary because when you
run a program in the LabWindows/CVI development environment, it executes as part of the
LabWindows/CVI process. When your program terminates, the operating system does not
release resources as it does when a process terminates. LabWindows/CVI releases as many
resources as it can, but your compiled module might have to do more. Also, if the program
suspends for debugging purposes, your compiled module might have to disable interrupts.
When you run a standalone executable, it always ex ecutes as a separate process. Thus, the run
state change callback facility is not necessary and does not work. External compilers report
link errors when you define
__RunStateChangeCallback in more than one object file. If
you require a run state change callback in a compiled module that you intend to use both in
LabWindows/CVI and an external compiler, National Instruments recommends that you put
the callback function in a separate source file and create a library (
National Instruments Corporation5-5LabWindows/CVI Programmer Reference Manual
__RunStateChangeCallback. The Notification of
.a) instead of an object file.
Chapter 5UNIX Compiler/Linker Issues
Using Externally Compiled Modules
In general, you can load objects compiled with the Sun compilers and the GNU gcc compiler
into LabWindows/CVI, with a few restrictions.
Restrictions on Externally Compiled Modules
You can use externally compiled modules with the following restrictions:
•The objects must not use any data types that are incompatible with the LabWindows/CVI
compiler or libraries. Incompatible data types include the following:
–
long double with any Sun compilers. A Sun compiler implements long double
as a 16-byte object, but LabWindows/CVI implements it as an 8-byte object.
–
long long with the Solaris 2 Sun compiler. LabW indows/CVI does not support this
non-ANSI type.
–Any enumeration type. Many compilers implement enumeration types with dif ferent
sizes and values.
•You canno t l oad a Solaris 2 object file when you run LabWi ndows/CVI under S ol ari s 1 .
However, you can load Solaris 1 objects when you run under Solaris 2.
Compiling Modules With External Compilers
Y ou can compile e xternal modules using LabW indows/CVI header files instead of the headers
the compiler supplies. To compile this way, you must define the preprocessor macro
_NI_sparc_ to the value 1 for Solaris 1 or to the value 2 for Solaris 2.
When using the Sun ANSI C compiler, use the
directory to the search list, as shown in the following command lines:
Solaris 1: acc -Xc -I/home/cvi/include -D_NI_sparc_=1 -c mysource.c
Solaris 2: cc -Xc -I/home/cvi/include -D_NI_sparc_=2 -c mysource.c
When using the GNU compiler, use the -nostdinc flag to disable the standard include f iles
and the
must use the
-I flag to add the LabWindows/CVI include directory to the search list. Also, you
-ansi flag. For example, to compile the file mysource.c using
LabWindows/CVI headers under Solaris 1, use the following command line.
You might see warnings about conflicting types for the built-in functions memcmp and
memcpy, but you can ignore them.
Note
These examples assume that /home/cvi/include is the LabWindows/CVI
header files directory. The actual path depends on how you install your copy of
LabWindows/CVI.
Y o u cannot use th e non-ANSI C Sun co mpiler cc because it d oes not recognize some ANSI C
constructs in the head er files, such as fu nction prototypes and th e keywords
volatile.
const, void, and
Locking Process Segments into Memory Using plock()
You can use the UNIX function plock to lock the text and data segments of your program
into memory. Ho wever , this function locks all segments of the LabWindows/CVI process, not
just the segments associated with your program. Also, because the text segments of
LabWindows/CVI programs actually reside in the data segment of the LabWindows/CVI
process, you must lock both text and data segments, using
lock all text into memory.
plock(PROCLOCK), in order to
Note
Your LabWindows/CVI process must have superuser privileges to use the
function.
UNIX Asynchronous Signal Handling
The following signals have special meaning in LabWindows/CVI:
•SIGPOLL (SIGIO) and SIGPIPE—The LabWindows/CVI TCP Library installs
signal handlers for
want to install handlers for these signals, you must call the LabWindows/CVI handlers
when your handlers are called. If you attempt to set the signal handler to
these signals while running in the LabWindows/CVI environment, LabWindows/CVI
restores its own handlers.
•SIGINT and SIGQUIT—Normally, the operating system generates these two signals
when you type certain keystrokes (<Ctrl-C> and <Ctrl-\>) in the window from which
you invoke LabWindows/CVI. If one of these signals occurs while your program is
running and you have not installed a handler for it, LabWindows/CVI suspends
your program the next time it calls a function that processes events (such as
ProcessSystemEvents). If your program does not call any event-processing
functions, it continues to run.
•SIGTERM—LabWindows/CVI treats
SIGQUIT. If this signal occurs while y our pr ogr am is ru nning and yo u ha v e n ot inst alled
a handler for it, LabWindows/CVI terminates the program, gives you a chance to save
your files, and exits. If
exits immediately.
•SIGBUS, SIGFPE, SIGILL, and SIGSEGV—These signals exist to allow for
hardware exceptions. Because execution cannot continue beyond the instruction that
caused the exception, LabWindows/CVI always catches these signals. If this signal
occurs while your program is running, LabWindows/CVI reports a fatal run-time error
SIGPOLL (SIGIO) and SIGPIPE. If you use the TCP Library and you
SIGTERM as a stronger version of SIGINT and
SIGTERM occurs when no program is running, Lab W indo ws/CVI
National Instruments Corporation5-7LabWindows/CVI Programmer Reference Manual
Chapter 5UNIX Compiler/Linker Issues
and suspends operation at the statement that caused the exception. If this signal occurs
when no program is running, LabWindows/CVI exits immediately.
You cannot use
signal, sigaction, sigset, or sigvec to make your program ignore the
signals this section lists.
NoteIf your program begins to loop indefinitely, you can often suspend execution by
sending a signal to the LabWindows/CVI process as follows:
1. Use the
2. Send the
LabWindows/CVI process number is 3478, the command
sends the
execution of your program in LabWindows/CVI, try using
If sending the
SIGTERM signal, which terminates not just you r program but also
ps command to identify the process number of LabWindows/CVI.
kill
-SIGNAL pid
SIGINT signal to LabWindows/CVI. When you want to suspend
SIGINT or SIGQUIT signal fails, you must use the stronger
command to that process. For example, if the
kill -INT 3478
SIGINT or SIGQUIT.
LabWindows/CVI.
NoteSome signals can cause LabWindows/CVI to dump core you are running a
program that does not install handlers for them.
Solaris 1 ANSI C Library Implementation
The C library that comes with Sun Solaris 1 (SunOS 4.1.x) does not comply with the ANSI C
standard as follows:
•Some ANSI C functions are missing from the library.
•Some library functions have different behavior than the ANSI standard specifies.
LabWindows/CVI corrects these problems by linking your programs to a supplemental C
library
libcfix.a, which is in the lib subdirectory of the LabWindows/CVI installation
directory . This library co ntains replacement functions fo r some Sun Solaris functions an d for
the ANSI functions that are not available in the Sun Solaris library. The names of the
replacement functions differ from the Sun Solaris function names and do not interfere with
programs or libraries t hat depend upon the non- ANSI behavior of s ome Sun Solaris functi ons.
The LabWindows/CVI ANSI header files contain macro definitions for the replacement
functions. When you compile with the LabWindows/CVI headers, your program references
the LabWindows/CVI replacement functions instead of the Sun Solaris versions.
Consider the case of
Sun Solaris 1 implementation of the
realloc, which LabWindo ws/CVI replaces with _cvi_realloc. The
realloc function fails when the first argument is
NULL. The ANSI standard requires that
libcfix.a, LabWindows/CVI defines _cvi_realloc, which treats a NULL
library
argument as the ANSI standard prescribes. The LabWindows/CVI header file