Microsoft SDK for Java

Calling Different Versions of DLL Functions

The J/Direct Message Box example didn't mention a subtle but important fact: USER32 does not export a function named MessageBox. Because the MessageBox function takes a String, it deals with Strings like all other Win32 functions do: by calling either the ANSI version or the Unicode version (named MessageBoxA and MessageBoxW, respectively). When you call MessageBox in C or C++, you actually are calling a macro that expands to either MessageBoxA or MessageBoxW, depending on whether the Unicode macro is defined.

By excluding or including modifiers to @dll.import, call the ANSI, Unicode, or optimal version of a DLL function.

The com.ms.dll package includes several classes (especially DllLib) that contain useful methods for extracting strings from native memory blocks, mapping raw pointers onto @dll.struct classes, copying bytes between various types, and other tasks.

Calling the ANSI Version of a DLL Function

By default, the Microsoft VM assumes that the ANSI version of MessageBox is the one needed. If you import the MessageBox function using @dll.import without a modifier as follows:

  /** @dll.import("USER32") */
  static native int MessageBox(int hwnd, String text,
                               String title, int style);

The Microsoft VM goes through the following steps.

  1. The strings "text" and "title" are converted to ANSI null-terminated strings.

  2. The VM attempts to find an export named MessageBox in USER32.DLL.

  3. This attempt fails. The VM then appends an "A" onto the name and looks for an export named MessageBoxA.

  4. This attempt succeeds, and the VM invokes the MessageBoxA function.

Calling the Unicode Version of a DLL Function

If you want to call the Unicode version of MessageBox, use the unicode modifier with the @dll.import directive:

  /** @dll.import("USER32",unicode) */
  static native int MessageBox(int hwnd, String text, String title,
                               int style);

Because the unicode modifier is present, the Microsoft VM will go through the following steps.

  1. The strings "text" and "title" are converted to Unicode null-terminated strings.

  2. The VM attempts to find an export named MessageBox in USER32.DLL.

  3. This attempt fails. The VM appends a "W" onto the name and looks for an export named MessageBoxW.

  4. This attempt succeeds, and the VM invokes the MessageBoxW function.

Calling the Optimal Version of a DLL Function

You might not always know in advance whether the ANSI or Unicode version is the best in a particular situation. Both have advantages and disadvantages. The default ANSI mode allows your code to run on any Win32 platform, but this causes unnecessary performance penalties on fully Unicode systems such as Microsoft® Windows NT®. The unicode modifier removes the performance penalty, but this restricts you to running on systems that implement the Unicode API.

The auto modifier lets the Microsoft VM decide which version of a DLL function is optimal based on the host operating system. The following example shows how to call the optimal version of the MessageBox function.

  /** @dll.import("USER32",auto) */
  static native int MessageBox(int hwnd, String text, String title,
                               int style);

When the auto modifier is present, the Microsoft VM determines at runtime whether the underlying platform supports the Unicode APIs. If Unicode is supported, the Microsoft VM acts as if the unicode modifier had been specified. Otherwise, the Microsoft VM behaves as if the ansi modifier had been specified. Thus, the auto modifier allows you to generate a single binary that runs well on both ANSI and Unicode Windows systems using the optimal API set available on the particular platform.

You can programmatically learn whether the auto modifier will select Unicode or ANSI on a particular platform by inspecting the system class com.ms.dll.DllLib. This class has a public integer field named systemDefaultCharSize. Its value is set to 1 (for ANSI) or 2 (for Unicode).

In general, the auto modifier should be used whenever you call Windows API functions. If you are calling your own DLLs, select either ansi (the default) or unicode depending on your needs.

The following shows how the Microsoft VM decides whether to use ANSI or Unicode when you use the auto modifier.

  1. The VM opens the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\Java VM and looks for the DWORD-named value DllImportDefaultType. This value can be one of the following:

    2 - ANSI: Always uses the ANSI version.

    3 - Unicode: Always uses the Unicode version.

    4 - Platform: Uses ANSI or Unicode depending on the platform.

  2. If the key does not exist or if it is set to 4 (indicating the platform), the VM calls the Win32 GetVersion function. The VM examines the high bit to determine whether the underlying platform is Microsoft® Windows® 95 or Microsoft® Windows NT®. If the platform is Windows 95, ANSI mode is used. Otherwise, Unicode mode is used.

It is not necessary to set the DllImportDefaultType registry key yourself. That key's main purpose is to allow the installation program to set the appropriate choice on future Windows platforms. You can programmatically query the preferred mode on your platform by reading the com.ms.dll.DllLib.systemDefaultCharSize field. This field will be set to 1 on ANSI systems, 2 on Unicode systems.

The ansi, unicode, and auto modifiers can also be used with the @dll.struct directive.

© 1999 Microsoft Corporation. All rights reserved. Terms of use.