Open source Java projects: Java Native Access

An easier way to access native code

1 2 3 4 5 Page 3
Page 3 of 5

Compile and run the application

This part is easy. Assuming that jna.jar,, and are located in the current directory, invoke javac -cp jna.jar;. to compile the application's source code. Assuming a Windows platform, invoke java -cp jna.jar;. LocalTime to run the application. You should see output similar to Listing 4.

Listing 4. Output generated from

Year is 2007
Month is 12
Day of Week is 3
Day is 19
Hour is 12
Minute is 35
Second is 13
Milliseconds are 156

Accessing joystick device info

Although the previous example introduces JNA, obtaining the local time and date is not actually a good use of this technology, or even JNI. Java's System.currentTimeMillis() method already returns this information, albeit expressed in milliseconds. Accessing a joystick device is a more appropriate use of JNA because Java does not provide an API for game controllers.

Ideally, you would build a platform-independent Java library that uses JNA to access the native Joystick APIs on Linux, Mac OS X, Windows, and Unix platforms. For brevity and convenience, this example will focus exclusively on accessing the Windows Joystick API. I'll also limit the focus to just a small part of the API.

As with GetLocalTime(), your first step is to identify the Joystick API's DLL. The name of this DLL is winmm.dll, which includes the Joystick API with other multimedia APIs -- winmm.dll is located in the same directory as kernel32.dll. You also need to know the C-based declarations for the joystick functions to be used. These function declarations are shown in Listing 5.

Listing 5. C-based declarations for some Joystick API functions

#define MAXPNAMELEN 32

typedef struct
   WORD  wMid;                  // manufacturer identifier
   WORD  wPid;                  // product identifier
   TCHAR szPname [MAXPNAMELEN]; // product name
   UINT  wXmin;                 // minimum x position
   UINT  wXmax;                 // maximum x position
   UINT  wYmin;                 // minimum y position
   UINT  wYmax;                 // maximum y position
   UINT  wZmin;                 // minimum z position
   UINT  wZmax;                 // maximum z position
   UINT  wNumButtons;           // number of buttons
   UINT  wPeriodMin;            // smallest supported polling interval when captured
   UINT  wPeriodMax;            // largest supported polling interval when captured

MMRESULT joyGetDevCaps(UINT IDDevice, LPJOYCAPS lpjc, UINT cbjc);

UINT joyGetNumDevs(VOID);

Functions of the Joystick API

Windows implements the Joystick API via several functions that begin with the joy prefix, and structures that various joy functions use. For example, joyGetNumDevs() returns the maximum number of joystick devices supported by the platform, and joyGetDevCaps() returns an attached joystick's capabilities.

The joyGetDevCaps() function takes three arguments:

  • A device ID ranging from 0 through joyGetNumDevs()-1
  • The address of a JOYCAPS structure that holds returned capability information
  • The size of the JOYCAPS structure in bytes

Although it appears otherwise, this function returns a 32-bit unsigned integer, where zero indicates an attached joystick.

The JOYCAPS structure identifies three types. In addition to the Windows WORD (16-bit unsigned short integer) type, which maps to Java's 16-bit signed short integer type, this structure specifies the Windows-defined UINT (32-bit unsigned integer) type, which maps to Java's 32-bit signed integer type, and the Windows text character type known as TCHAR.

Microsoft introduced TCHAR to let developers smoothly migrate functions with ASCII text arguments to functions with wide character (think Unicode) text arguments. Also, functions with text arguments are implemented as macros that map to ASCII or wide-character functions. For example, joyGetDevCaps() is really a macro that maps to joyGetDevCapsA() and joyGetDevCapsW().

1 2 3 4 5 Page 3
Page 3 of 5