| Customize Help

MIL custom data types, void pointers, extensions, and portability functions



MIL features data types, constants, and functions that can improve your application's portability and operating system independence. In C++, MIL also supports the standard string and vector objects to simplify handling of strings and arrays, respectively.

MIL custom data types

In addition to the standard data types available in C and C++, MIL introduces the following predefined data types, to ensure better compatibility and portability of MIL applications under different operating systems:

  • MIL_ID. Specifies a value that is a MIL identifier. The MIL_ID data type is used to identify objects (for example, buffers, systems, and contexts) which are allocated using MIL within an application.

  • MIL_INT. Specifies a value that is an integer. The MIL_INT data type is used as a supplement to the more conventional long and int data types. The MIL_INT data type is a 32-bit value on a 32-bit operating system, and a 64-bit value on a 64-bit operating system.

  • MIL_UINT. Specifies a value that is an unsigned integer. Its data depth is the same as that of the MIL_INT data type.

  • MIL_DOUBLE. Specifies a value that is a double precision, floating-point number.

  • MIL_FLOAT. Specifies a value that is a single precision, floating-point number.

  • MIL_UUID. Specifies a universally unique identifier that is used for identification purposes across unrelated systems and applications. For example, a MIL_UUID value is used as an entry key in a dataset context for the MIL Classification module.

In addition to the MIL_INT and MIL_UINT data types, MIL also has signed and unsigned, fixed length versions of these data types: MIL_INT8, MIL_UINT8, MIL_INT16, MIL_UINT16, MIL_INT32, MIL_UINT32, MIL_INT64, and MIL_UINT64.

MIL also introduces the following predefined data types, to ensure better compatibility and portability of applications regardless of whether they are compiled for ASCII or Unicode character sets:

  • MIL_TEXT_CHAR. Specifies an array of characters. The MIL_TEXT_CHAR data type is used as a replacement for the more conventional char data type.

  • MIL_STRING. Specifies a string object. This object can be used wherever an array of MIL_TEXT_CHAR, address of a MIL_TEXT_PTR, or address of a MIL_CONST_TEXT_PTR should be used. However, it should be noted that MIL_STRING cannot be used when dealing with an array of multiple strings. The MIL_STRING data type is only available in C++. A variable of this type can be manipulated like a standard C++ string (std::string).

  • MIL_STRING_STREAM. Specifies a string stream object. The MIL_STRING_STREAM data type is only available in C++. A variable of one of this type can be manipulated like a standard C++ string stream (std::stringstream).

  • MIL_TEXT_PTR. Specifies a pointer to an array of characters. The MIL_TEXT_PTR data type is used as a replacement for the more conventional char* data type.

  • MIL_CONST_TEXT_PTR. Specifies a pointer to an array of constant characters. The data type is used as a replacement for the more conventional const char* data type.

  • MIL_WINDOW_HANDLE. Specifies the handle to a window. The data type is used as a replacement for the more conventional HWND data type in Windows and the Window data type when using the Xlib library in Linux.

There is a macro called MIL_TEXT which converts the provided string to the proper encoding (ASCII or Unicode) for the application. Its syntax is: MIL_TEXT("Text to be converted.").

There is a macro called M_TO_STRING which converts the provided numeric data to a string with the proper encoding (ASCII or Unicode) for the application. Its syntax is: M_TO_STRING(number). This macro is only available when using C++11 (or later), and maps directly to std::to_string or std::to_wstring (depending on your project settings).

MIL also features several standard objects in C++ to simplify the handling of strings and arrays, respectively. For more information, see the Strings and arrays subsection of this section.

Void pointers

In MIL, there are functions, predominantly M...Inquire() and M...GetResult() functions, where one (or more) of their parameters takes a void pointer. This allows for a more general API where one function (within a module) can retrieve or set information of different data types (for example, MdispInquire() can be used to retrieve the width of the display (MIL_INT) and the title of the display (array of MIL_TEXT_CHAR). The expected data type for these void pointer parameters is determined in one of two ways:

  • The data type is intrinsically determined by the setting of another parameter.

    For example, consider the MbufInquire() function. When the InquireType parameter of this function is set to M_ALLOCATION_OVERSCAN_SIZE, a MIL_INT value is returned, and, therefore, the UserVarPtr parameter expects the address of a variable of type MIL_INT. However, when the InquireType parameter is set to M_ANCESTOR_ID, the UserVarPtr parameter expects the address of a variable of type MIL_ID.

    // Two calls to the same function where different data types are expected.
    //
    // Value1 should point to a MIL_INT
    /*Pointer for last parameter of MbufInquire should reference a MIL_INT*/
    MIL_INT     Value1;
    MbufInquire(BufId, M_ALLOCATION_OVERSCAN_SIZE, &Value1);
    //
    /*Pointer for last parameter of MbufInquire should reference a MIL_ID*/
    MIL_ID      Value2;
    MbufInquire(BufId, M_ANCESTOR_ID, &Value2);
    

    In the MIL help, a parameter association table is used to list the independent parameter setting and the expected data type of the address to pass to its dependent void pointer parameter(s); the data type is presented in green text. If the expected data type is not that of an array, the expected data type will be shown inline. However, if it is of an array, or if, given the setting, one of multiple data types might be expected, you will be able to expand the data type information to see in which situation one data type is expected over the other, and in the case of an array, to see how large the array must be.

  • The data type is determined by a modifier (for example, M_TYPE_MIL_DOUBLE) added to the setting of another parameter.

    For example, consider the MblobInquire() function. The InquireType parameter specifies type of information about which to inquire. The UserVarPtr parameter specifies the address at which to write the requested information. The UserVarPtr parameter is a void pointer, and by default requires that you pass it the address of a MIL_DOUBLE value. However, if M_TYPE_MIL_INT is added to the setting of InquireType, the UserVarPtr parameter expects the address of a variable of type MIL_INT.

    // Two calls to the same function where different data types are expected.
    //
    /*Pointer for last parameter of MgraInquire should reference a MIL_DOUBLE*/
    MIL_DOUBLE     Value3;
    MgraInquire(ContextGraId, M_DRAW_OFFSET_X, &Value3);
    //
    /*Pointer for last parameter of MgraInquire should reference a MIL_INT*/
    MIL_INT    Value4;
    MgraInquire(ContextGraId, M_DRAW_OFFSET_X + M_TYPE_MIL_INT, &Value4);
    

    The ability to modify the expected data type is typically only available for processing or analysis modules' M...Inquire() functions and M...GetResult() functions. See the function(s)' reference description to establish if the data type can be changed using a modifier.

The general description of a void pointer parameter includes a complete list of the possible data types that the parameter can take. This list also includes the data types that are expected when using a modifier (M_TYPE_...). For more information concerning void parameters in languages other than C/C++, see the appropriate language-specific chapter.

Strings and arrays

Strings in MIL are typically represented using arrays of type MIL_TEXT_CHAR, or a MIL_TEXT_PTR or MIL_CONST_TEXT_PTR. In C++, you can instead use a MIL_STRING.

MIL_STRING is resized automatically when calling an M...Inquire() or M...GetResult() function that returns a string. This makes it easier to inquire or get such a result, because you don't need to inquire the string length, allocate an array of this size, and then inquire/get the string.

It should be noted that MIL_STRING cannot be used when dealing with an array of strings, that is, if the function is returning multiple null-terminated strings into an array.

In C++, all MIL functions that take an input or output array as a parameter have overloaded versions that allow you to pass a reference to a standard C++ vector (std::vector) to that parameter instead. Some output parameters allow you to pass a combination constant (for example; M_TYPE_...) to cast the returned data to a required data type. When using a vector, don't pass the combination constant; just pass a vector of the required-type. MIL will automatically return the data cast to the type of the vector.

Note that for these output parameters, the vector can be the expected data type of the parameter or one of the listed cast types for that output parameter (for example M_TYPE_...).

Typically, when using an input vector, MIL will automatically determine the array size based on the size of the vector, with the exception of cases where only a subset of the vector should be specified (for example, MbufPut1d()).

When using a vector for an output parameter, it is not necessary to determine the size of the array before calling a function, since MIL will resize the output vector automatically.

A vector overload function might call more than one MIL function. Vector overload functions might call more MIL functions in debug mode than in release mode, to validate parameters. When using vector overload functions in debug mode, you might notice an increased performance slowdown in addition to the typical performance slowdown when running in debug mode.

The following code snippet illustrates how to use a standard vector (std::vector) overload function for input and output array parameters.

// Get pixel values from the image. Vector is resized automatically.
// Data type MIL_UINT8 is checked against the buffer data type in debug mode.
std::vector<MIL_UINT8> Pixels;
MbufGet(ImageId, Pixels);

// Do some operations on the pixel values...

// Put values back into the image. Size and data type are validated in debug mode.
MbufPut(ImageId, Pixels);

The following code snippet illustrates how to use a standard vector (std::vector) overload function that has a parameter defining the size of the array. In this case, MgraDots() is called to draw dots in an image. M_DEFAULT is passed to the NumberOfDots parameter. MIL will automatically determine the appropriate size based on the number of elements in the vector. Refer to individual function descriptions for more information on what to pass to an array size parameter.

const std::vector<MIL_INT> DotsX {1, 4, 8, 100};
const std::vector<MIL_INT> DotsY {2, 5, 9, 101};
MgraDots(ContextGraId, ImageId, M_DEFAULT, DotsX, DotsY, M_DEFAULT);

The following code snippet illustrates how to instantiate and use a standard vector (std::vector) when calling a function where a casting combination flag would typically be required.

MimHistogram(ImageId, HistResultId);

// Get histogram values. Vector is resized automatically. Data is cast to the
// vector type (MIL_INT32) without having to specify a combination flag.
std::vector<MIL_INT32> Histogram;
MimGetResult(HistResultId, M_VALUE, Histogram);

MIL directory constants

MIL provides several string constants for accessing special directories, such as the default MIL installation, contexts, and images directories. These constants are guaranteed to be correct for the local computer, even if MIL is not installed in the default location. You can increase the portability of your MIL application by prepending these constants to strings that contain file paths, instead of using hard-coded paths which might not be correct for all computers on which your application will run.

Typically, these directories are only used when accessing content related to MIL examples (except for the operating system's temporary directory).

The following constants are provided:

  • M_INSTALL_DIR. The path to the root directory of the local MIL installation. This constant is equivalent to using MappInquire() with M_MIL_DIRECTORY_INSTALL.

    By default on a Windows platform (for 64-bit MIL), this path is C:\Program Files\Matrox Imaging\MIL.

    By default on a Linux platform, this path is /opt/matrox_imaging/mil.

  • M_IMAGE_PATH. The path to the local MIL images directory. This constant is equivalent to using MappInquire() with M_MIL_DIRECTORY_IMAGES.

    By default on a Windows platform (for 64-bit MIL), this path is C:\Program Files\Matrox Imaging\Images.

    By default on a Linux platform, this path is /opt/matrox_imaging/mil/images.

  • M_CONTEXT_PATH. The path to the local MIL contexts directory. This constant is equivalent to using MappInquire() with M_MIL_DIRECTORY_CONTEXTS.

    By default on a Windows platform (for 64-bit MIL), this path is C:\Program Files\Matrox Imaging\Contexts.

    By default on a Linux platform, this path is /opt/matrox_imaging/mil/contexts.

  • M_USER_DLL_DIR. The path to the MIL folder that stores the DLLs which contain user-defined MIL slave functions. For more information on user-defined MIL functions, see the MIL Function Development module section of Chapter 53: The MIL function development module.

    By default on a Windows platform (for 64-bit MIL), this path is C:\Users\Public\Documents\Matrox Imaging\MIL\UserDLL.

    By default on a Linux platform, this path is /opt/matrox_imaging/mil/lib. This folder is only accessible by users in the MIL administrator group.

  • M_TEMP_DIR. The path to the operating system's temporary directory. On a Windows platform, this is equivalent to the environment variable %TEMP%.

    By default on a Windows platform, this path is C:\Users\<USERNAME>\AppData\Local\Temp.

    By default on a Linux platform, this path is /tmp.

    On a Linux platform, the contents of the temporary folder is erased when the computer is restarted.

M_MIL_USE_SAFE_TYPE extension

When using void pointers it is possible to make a mistake and pass a value with the wrong data type. These errors can cause unexpected behavior such as: stack corruption, array overflow, uninitialized returned data, and segmentation faults. MIL includes the M_MIL_USE_SAFE_TYPE extension to help you find these errors.

Note that the extension is also used when validating or attempting to cast a standard vector (std::vector) or MIL_STRING type parameter.

Note that this extension is not supported under Linux.

When the M_MIL_USE_SAFE_TYPE extension is enabled, an error message is returned if the data type of the variable whose address is passed to a void pointer parameter does not match the expected data type. By default, the M_MIL_USE_SAFE_TYPE extension is enabled when compiling in debug mode.

Note that the M_MIL_USE_SAFE_TYPE extension is only available if you are using a C++ compiler under Windows.

You might want to skip the verification performed by the M_MIL_USE_SAFE_TYPE extension if:

  • The data type of a value is unknown at the time the function is called. This typically occurs when the MIL function is wrapped inside another function in the application. For example:

    MIL_INT UserWrapperAroundMbufInquire(MIL_ID BufId, MIL_INT64 InquireType, void *UserVarPtr){
    return MbufInquire(BufId, InquireType, UserVarPtr);
    }
    
  • The data type of the value passed to a function is not one of the expected data types accepted by a function (for example, when a custom data type is defined in the application).

    MIL_INT8 *Data = (MIL_INT8 *)malloc(sizeof(MIL_DOUBLE) / sizeof(MIL_INT8));
    MmodGetResult(ResultId, M_GENERAL, M_NUMBER, Data);
    Number = *((double*)Data);
    free(Data);
    

To disable the M_MIL_USE_SAFE_TYPE extension entirely, include the #define M_MIL_USE_SAFE_TYPE 0 statement before the #include <mil.h> statement in the application code. When the extension is excluded, all MIL overloads are called without any data type verification.

Portability functions

In addition to the functions available in the C/C++ standard library, MIL introduces the following functions to ensure better compatibility and portability of applications regardless of whether they are compiled for ASCII or Unicode character sets:

Function in the C/C++ standard library

Portable MIL version of the function

Description

abs

MIL_INT MosAbs(MIL_INT n)

Calculates the absolute value of "n".

getch

MIL_INT MosGetch()

Reads a character or keystroke from the standard input (keyboard). After a keystroke is read, the application instantly resumes.

getchar

MIL_INT MosGetchar()

Reads a character from the standard input (keyboard). After a keystroke is read, the application waits for the Enter key to be pressed before resuming.

kbhit

MIL_INT MosKbhit()

Returns a non-zero value once a keystroke is read.

main

MIL_INT MosMain()

Specifies the first function to execute.

printf

MIL_INT MosPrintf(MIL_CONST_TEXT_PTR FormatString, Arg1, Arg2, …)

Prints formatted data to the console. The FormatString parameter is a MIL_TEXT string that can optionally contain format specifiers that will be replaced with the subsequent arguments (Arg1, Arg2, ...). Format specifiers are introduced by the "%" character within the FormatString value. For example, the following code: MosPrintf(MIL_TEXT("A character: %c and an integer: %d"), 'b', 523); outputs the following sentence to the console: A character: b and an integer: 523.

sleep

MIL_INT MosSleep(MIL_INT waitTime)

Suspends an application for the specified period of time.

sprintf_s

MIL_INT MosSprintf(array of type MIL_TEXT_CHAR DstArrayPtr, MIL_INT size, MIL_CONST_TEXT_PTR FormatString, Arg1, Arg2, …)

Writes formatted data to a string. The DstArrayPtr parameter specifies the array of characters in which to store the formatted data as a string. The size is the maximum size of the array of characters, including the NULL-termination character. The FormatString parameter is a MIL_TEXT string that can optionally contain format specifiers that will be replaced with the subsequent arguments (Arg1, Arg2, ...). Format specifiers are introduced by the "%" character within the FormatString value. For example, the following code: MosSprintf(String, MIL_TEXT("A character: %c and an integer: %d."), 'b', 523); saves the following sentence in DstArrayPtr: A character: b and an integer: 523.

strcat_s

MIL_INT MosStrcat(MIL_TEXT_PTR strDestination, MIL_INT size, MIL_TEXT_PTR strSource)

Joins strings.

strcmp

MIL_INT MosStrcmp(MIL_TEXT_PTR string1, MIL_TEXT_PTR string2)

Compares two strings.

strcpy_s

MIL_INT MosStrcpy(MIL_TEXT_PTR strDestination, MIL_INT size, MIL_TEXT_PTR strSource)

Copies characters of one string to another.

strlen

MIL_INT MosStrlen(MIL_TEXT_PTR str)

Calculates and returns the length of a string.

strlwr

MIL_INT MosStrlwr(MIL_TEXT_PTR str)

Converts a string to lowercase.

strupr

MIL_INT MosStrupr(MIL_TEXT_PTR str)

Converts a string to uppercase.

For more information on the above-mentioned functions of the C/C++ standard library, refer to MSDN.