Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 5
The use of TCHAR and the business of mapping macros to functions only slightly complicate the task of transitioning the C-based declarations
to a JNA-based interface -- do you work with the ASCII or wide-character version of a joystick function? Both versions are
shown in the interface below.
// WinMM.java
import com.sun.jna.*;
import com.sun.jna.win32.*;
public interface WinMM extends StdCallLibrary
{
final static int JOYCAPSA_SIZE = 72;
public static class JOYCAPSA extends Structure
{
public short wMid;
public short wPid;
public byte szPname [] = new byte [32];
public int wXmin;
public int wXmax;
public int wYmin;
public int wYmax;
public int wZmin;
public int wZmax;
public int wNumButtons;
public int wPeriodMin;
public int wPeriodMax;
}
int joyGetDevCapsA (int id, JOYCAPSA caps, int size);
final static int JOYCAPSW_SIZE = 104;
public static class JOYCAPSW extends Structure
{
public short wMid;
public short wPid;
public char szPname [] = new char [32];
public int wXmin;
public int wXmax;
public int wYmin;
public int wYmax;
public int wZmin;
public int wZmax;
public int wNumButtons;
public int wPeriodMin;
public int wPeriodMax;
}
int joyGetDevCapsW (int id, JOYCAPSW caps, int size);
int joyGetNumDevs ();
}
Listing 6 does not introduce new JNA features. Instead, it reinforces the convention of naming the interface after a native
library. It also shows how to map the TCHAR array to equivalent byte and char Java arrays. Finally, it reveals structure size constant declarations. Listing 7 shows the usefulness of these constants
when invoking joyGetDevCapsA() and joyGetDevCapsW().
// JoystickInfo.java
import com.sun.jna.*;
public class JoystickInfo
{
public static void main (String [] args)
{
WinMM lib = (WinMM) Native.loadLibrary ("winmm", WinMM.class);
int numDev = lib.joyGetNumDevs ();
System.out.println ("joyGetDevCapsA() Demo");
System.out.println ("---------------------\n");
WinMM.JOYCAPSA caps1 = new WinMM.JOYCAPSA ();
for (int i = 0; i < numDev; i++)
if (lib.joyGetDevCapsA (i, caps1, WinMM.JOYCAPSA_SIZE) == 0)
{
String pname = new String (caps1.szPname);
pname = pname.substring (0, pname.indexOf ('\0'));
System.out.println ("Device #"+i);
System.out.println (" wMid = "+caps1.wMid);
System.out.println (" wPid = "+caps1.wPid);
System.out.println (" szPname = "+pname);
System.out.println (" wXmin = "+caps1.wXmin);
System.out.println (" wXmax = "+caps1.wXmax);
System.out.println (" wYmin = "+caps1.wYmin);
System.out.println (" wYmax = "+caps1.wYmax);
System.out.println (" wZmin = "+caps1.wZmin);
System.out.println (" wZmax = "+caps1.wZmax);
System.out.println (" wNumButtons = "+caps1.wNumButtons);
System.out.println (" wPeriodMin = "+caps1.wPeriodMin);
System.out.println (" wPeriodMax = "+caps1.wPeriodMax);
System.out.println ();
}
System.out.println ("joyGetDevCapsW() Demo");
System.out.println ("---------------------\n");
WinMM.JOYCAPSW caps2 = new WinMM.JOYCAPSW ();
for (int i = 0; i < numDev; i++)
if (lib.joyGetDevCapsW (i, caps2, WinMM.JOYCAPSW_SIZE) == 0)
{
String pname = new String (caps2.szPname);
pname = pname.substring (0, pname.indexOf ('\0'));
System.out.println ("Device #"+i);
System.out.println (" wMid = "+caps2.wMid);
System.out.println (" wPid = "+caps2.wPid);
System.out.println (" szPname = "+pname);
System.out.println (" wXmin = "+caps2.wXmin);
System.out.println (" wXmax = "+caps2.wXmax);
System.out.println (" wYmin = "+caps2.wYmin);
System.out.println (" wYmax = "+caps2.wYmax);
System.out.println (" wZmin = "+caps2.wZmin);
System.out.println (" wZmax = "+caps2.wZmax);
System.out.println (" wNumButtons = "+caps2.wNumButtons);
System.out.println (" wPeriodMin = "+caps2.wPeriodMin);
System.out.println (" wPeriodMax = "+caps2.wPeriodMax);
System.out.println ();
}
}
}
Although similar to LocalTime, JoystickInfo executes WinMM lib = (WinMM) Native.loadLibrary ("winmm", WinMM.class); to allocate a WinMM instance and load winmm.dll. It also executes WinMM.JOYCAPSA caps1 = new WinMM.JOYCAPSA (); and WinMM.JOYCAPSW caps2 = new WinMM.JOYCAPSW (); to allocate needed structure instances.
| Converting a C string to a Java string |
|---|
The pname = pname.substring (0, pname.indexOf ('\0')); code fragment converts a C string to a Java string. Without this conversion, the \0 string terminator and any following garbage characters would be part of the Java string.
|
Assuming that jna.jar, WinMM.java, and JoystickInfo.java are located in the current directory, invoke javac -cp jna.jar;. JoystickInfo.java to compile the application's source code. Assuming a Windows platform, invoke java -cp jna.jar;. JoystickInfo to run the application. If no joystick devices are attached, you should see the output shown in Listing 8.
joyGetDevCapsA() Demo
---------------------
joyGetDevCapsW() Demo
---------------------
This header-only output is due to each joyGetDevCap() invocation returning a non-zero value, which indicates either a non-attached joystick/game controller or an error. To generate
more interesting output, attach one of these devices to your platform and re-run JoystickInfo. For example, I received the output shown below after attaching a Microsoft SideWinder Plug and Play Game Pad device:
joyGetDevCapsA() Demo
---------------------
Device #0
wMid = 1118
wPid = 39
szPname = Microsoft PC-joystick driver
wXmin = 0
wXmax = 65535
wYmin = 0
wYmax = 65535
wZmin = 0
wZmax = 65535
wNumButtons = 6
wPeriodMin = 10
wPeriodMax = 1000
joyGetDevCapsW() Demo
---------------------
Device #0
wMid = 1118
wPid = 39
szPname = Microsoft PC-joystick driver
wXmin = 0
wXmax = 65535
wYmin = 0
wYmax = 65535
wZmin = 0
wZmax = 65535
wNumButtons = 6
wPeriodMin = 10
wPeriodMax = 1000
jna.jar and examples.jar from the JNA downloads page.
Archived Discussions (Read only)