Admin Production ni-theme
Current Publication

Porting 32-bit Code to 64-bit Code

LabWindows/CVI

Porting 32-bit Code to 64-bit Code

Generally, writing code for 64-bit applications is no different than for 32-bit applications. The primary difference is that you have access to more memory; the exact amount of memory depends on your processor. In 64-bit applications, pointers expand to 64 bits, meaning that you can address more memory than with 32-bit applications. Because the size of pointers is different between 32-bit and 64-bit applications, you can no longer assume that pointers are 32 bits long. You will need to update any code that makes this assumption.

Use the following list as a guide to update your code to make it 64-bit ready.

  • First compile your code in 32-bit and 64-bit mode to determine the types of errors and warnings that occur in your code. Examine and fix each warning that LabWindows/CVI returns.
  • Use data types that do not rely on a specific pointer size but instead are defined as either 32-bit or 64-bit depending on the bitness of your application, such as the following data types.

    Data type Description Size on 32-bit applications Size on 64-bit applications
    size_t, ssize_t size_t is an unsigned integer type, and ssize_t is a signed integer type. Both are used to represent the size or number of objects. size_t is returned by sizeof operator. 32 64
    intptr_t, uintptr_t Integer types capable of storing a pointer value. Used primarily for performing pointer arithmetic. 32 64
    ptrdiff_t Signed integer type representing a relative offset from a pointer, or the result of subtracting two pointers. 32 64
  • Do not use fixed-size types to store pointers.

    • LabWindows/CVI reports errors if you cast pointers to fixed-size data types such as int or DWORD, assign fixed-size data types to pointers, or create a function that returns a pointer as a fixed-size data type.
    • If you need to use a pointer as an integer in arithmetic or logical operations, use uintptr_t or intptr_t as the data type.
    • If you need to update variable data types to size_t or ssize_t from int or long, make sure that do you not introduce errors in comparison logic or overflow.
    • Although it is also a 64-bit quantity, the double data type cannot represent every value that the size_t, ssize_t, or uintptr_t types can. Converting a variable of size_t, ssize_t, or uintptr_t to a double might truncate the value of the variable.
  • Use uintptr_t to store pointer data in user interface controls. Because the size of this data type is different between 32-bit and 64-bit applications and because the LabWindows/CVI development environment is a 32-bit application, intptr_t and uintptr_t are 64-bit in the User Interface Editor; however, depending on the bitness of the application, they are converted to 32-bit or remains 64-bit at run time.
  • Numeric literal values are 32-bit unless otherwise specified.

    • It is especially important for you to note the type of a numeric literal if you use a literal with size_t, ssize_t, ptrdiff_t, intptr_t, or uintptr_t values.
    • There may be times when you must explicitly cast a literal value to a specific data type, such as with bit shift operations.
  • Use new formatting specifiers for pointers with functions such as printf or scanf.

    • For pointers, use %p instead of %x. The %x specifier truncates the pointer value to the low 32 bits.
    • For size_t and ssize_t data types, use the z format modifier.

      For ptrdiff_t, intptr_t, and uintptr_t data types, use the t format modifier.

      You can use both z and t with the following specifiers: d, i, o, u, x, and X. If you omit z or t and use only %d, for example, your value is truncated to the low 32 bits.
    • Use the b0 modifier in calls to Formatting and I/O Library functions to format arguments with size_t, ssize_t, ptrdiff_t, intptr_t, or uintptr_t data types. For 32-bit applications, the b0 modifier represents 4 bytes. For 64-bit applications, the b0 modifier represents 8 bytes.
  • Take note of files that include size_t, ssize_t, ptrdiff_t, intptr_t, and uintptr_t types that you save to disk or transfer to another program according to a given protocol.

    • Pointers and size_t, ssize_t, ptrdiff_t, intptr_t, and uintptr_t types take up different amounts of space depending on the bitness of your application. If your program writes these kinds of data to a file, consider whether the file might be loaded from both 32- and 64-bit programs. You might need to update your loading code to accommodate files written for both 32- and 64-bit applications.
    • Review reading/writing code for hard-coded assumptions about structure or data sizes.
  • Use the _NI_mswin64_ and _WIN64 macros to conditionally compile code for use only in 64-bit applications.

    When you compile in 64-bit mode, note that both the _WIN64 and _WIN32 macros are defined. For this reason, always use #ifdef _WIN64 for 64-bit only code. On the other hand, _NI_mswin64_ is defined only for 64-bit applications and _NI_mswin32_ is defined only for 32-bit applications.
  • Review unions containing size_t, ssize_t, ptrdiff_t, intptr_t, and uintptr_t types. If a union contains one of these types and provides multiple ways to access the same data, make sure that the other member(s) match up properly.
  • In structures, the size of items of types size_t, ssize_t, ptrdiff_t, intptr_t, and uintptr_t are different between 32-bit applications and 64-bit applications. In order to prevent unexpected results when switching between 32-bit and 64-bit, use the sizeof operator to find the size of these items.
  • Call the GetTimerTickData function to obtain the value of the time of the current EVENT_TIMER_TICK callback and the time elapsed since the last EVENT_TIMER_TICK callback instead of using the values returned in the eventData1 and eventData2 parameters of the EVENT_TIMER_TICK event.
  • Call KeyPressEventIsLeadByte, KeyPressEventIsTrailByte, GetKeyPressEventVirtualKey, GetKeyPressEventCharacter, GetKeyPressEventModifiers, and SetKeyPressEventKey to obtain or set the value of the eventData2 parameter of the EVENT_KEYPRESS event.
  • Call GetPanelEventRect or SetPanelEventRect to obtain or set the value of the eventData2 parameter of the EVENT_PANEL_SIZING and EVENT_PANEL_MOVING events.
  • You must regenerate files that you generated using the Create ActiveX Server and Create ActiveX Controller wizards so that you can compile and run those projects as 64-bit applications.
  • LabWindows/CVI uses __fastcall by default as the calling convention for 64-bit projects; thus, you do not need to specify a calling convention for 64-bit projects.

    You can specify either __cdecl or __stdcall as the calling convention for 32-bit projects.
  • The following parameters, which were declared as integer variables in versions of LabWindows/CVI earlier than 2009, have updated data types:

    Parameter Name Function Updated Data Type
    threadFunctionID CmtScheduleThreadPoolFunction CmtThreadFunctionID
    threadFunctionID CmtScheduleThreadPoolFunctionAdv CmtThreadFunctionID
    poolHandle CmtNewThreadPool CmtThreadPoolHandle
    callbackID CmtInstallThreadPoolCallback CmtThreadPoolCallbackID
    queueHandle CmtNewTSQ CmtTSQHandle
    callbackID CmtInstallTSQCallback CmtTSQCallbackID
    variableHandle CmtNewTSV CmtTSVHandle
    lockHandle CmtNewLock CmtThreadLockHandle
    variableHandle CmtNewThreadLocalVar CmtTLVHandle


    If you use these functions and need to build your project in LabWindows/CVI 9.0.1 or earlier, you must #include cvi2009compat.h in your source file. cvi2009compat.h is installed in Program Files\National Instruments\Shared\CVI\Include with this version of LabWindows/CVI.

    Note Note  If you need to use cvi2009compat.h with versions of LabWindows/CVI earlier than 8.5 or if you uninstall this version of LabWindows/CVI, you must copy the header file from <Program Files>\National Instruments\Shared\CVI\Include to <Program Files>\National Instruments\CVIversion\Include, where version corresponds to the version of LabWindows/CVI you are using to build your project.

    (Linux) If you need to use cvi2009compat.h with versions of the LabWindows/CVI Run-Time Module for Linux earlier than 2010 or if you uninstall this version of the LabWindows/CVI Run-Time Module for Linux, you must copy the header file from /usr/local/natinst/cvi2010/include to /usr/local/natinst/cvi80/include.
  • Review the list of common compiler warnings as you prepare your code.
  • Review the LabWindows/CVI functions, attributes, and events that were updated for 64-bit readiness. Some of the updates might require you to update your programs.