If you looked at the DisplayTime function shown in Listing 22.2, you ran across a few items that haven't been discussed yet. As mentioned earlier, the common language runtime will use data types that are compatible with one another when marshaling data between managed and unmanaged code. However, the String object can be represented by several different native C data types. If you need to call a function contained within an unmanaged DLL that contains different data types the String object could represent, you must use the MarshalAs attribute when creating the function definition. An example of one of these functions is the MultiByteToWideChar function, which is used to convert a single- or multibyte string to a wide string. The third parameter to that function expects a LPTSTR (char*) data type, and the fifth parameter expects LPWSTR (wchar_t*). However, for the function definition, you want to use a String object for both of these parameters. To accomplish this, use the MarshalAs attribute, which takes a data type as a parameter specified by the UnManagedType enumeration, as shown on lines 46 and 48 of Listing 22.2.
In order to test the MultiByteToWideChar function, you will also have to create a function definition for the wide string version of the MessageBox function. This is quite similar to the method you used for MessageBoxA, with the only difference being the entry point name, MessageBoxW.
You are now ready to compile and run your application. If everything works correctly, the first message box will be displayed showing that the connection to your unmanaged class has been made. After that message box is dismissed, another message box will be displayed that shows the results of calling the GetLocalTime function using the custom data type. Finally, the last message box that is displayed is the wide version of the message box whose parameters were marshaled by using the MarshalAs attribute. This message box can be seen in Figure 22.5.