J/Direct Native Library Declarations

M. Gallant 09/07/2000

Microsoft J/Direct technology enables easy access to the Win32 API directly from Java using special win32-specific directives. The following code examples show the two basic methods to declare the win32 API native methods:

Explicit Declaration


public class Simple
{
    public static void main(String args[])
    {
        try {
            MessageBox(0, "MessageBox successfully called.", "Java", 0);
        } catch (UnsatisfiedLinkError ule) {
            System.err.println("Caught exception: " + ule);
            System.err.println("Probably wrong version of Java compiler.");
        }
    }

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

Referenced Separate Class Declaration

Microsoft provides a class of declarations of the more commonly used win32 APIs in the com.ms.win32 package. Note that not ALL native functionality is represented in this package. For example, the standard C Runtime Library functions (from MSVCRT.dll) are not declared in this package.

import com.ms.win32.*;
public class Simple
{
  public static void main(String args[])
    {
      try {
        User32.MessageBox(0, "MessageBox successfully called.", "Java", 0);
        } catch (UnsatisfiedLinkError ule) {
          System.err.println("Caught exception: " + ule);
          System.err.println("Probably wrong version of Java compiler.");
    }
  }
}
Notice that using this approach, the class name must be prepended (User32 in this case) to the native function call since the declaration exists in a separate class.

Using the Standard C Runtime Library Functions from Java

The Standard C Runtime Library functions (e.g. printf(..)) are available by explicitly declaring the MSVCRT.dll library. For example:

class PrinterCRT {
   public static void main(String args[])
   {
     int num = 10 ;
     System.out.println("Table of roots\n") ;
     for (int i=2; i<50; i++) {
      double rt = Math.sqrt(i) ;
      printf("  %4d %#12.6g\n", i, rt) ;
     }
   }
   
   /** @dll.import("MSVCRT.DLL") */
   private static native int 
    printf(String formattext, int num, double data);
}


File I/O Example

The sample below shows how to read files into byte arrays using J/Direct. Two versions are given. The first version references the win32 packaged wrapper classes, com.ms.win32.* which are included in the Microsoft IE4+ runtime JVM. This approach simplifies the source code considerably, and you don't need to explicitly deploy the structs "helper" classes yourself. The second version includes explicit inline native function declarations for functions and structs.

Java Package Wrappers Version


/* J/Direct Win32 Java application to read in file into buffer
   Uses import package reference for native method declarations and structs.
    					M. Gallant  09/06/2000      */

import com.ms.win32.*;


class LoadFileToStringImp {

   public static void main(String args[])
   {
     long start_t, stop_t ;

     SECURITY_ATTRIBUTES secatt = new SECURITY_ATTRIBUTES() ;

     System.out.println("Loading " + args[0] + " into byte buffer ..... \n") ;
      start_t = System.currentTimeMillis() ;
      int filehandle = Kernel32.CreateFile(args[0], win.GENERIC_READ, win.FILE_SHARE_READ, secatt, 
                       win.OPEN_EXISTING, win.FILE_ATTRIBUTE_READONLY, 0) ;
      if(filehandle == win.INVALID_HANDLE_VALUE)
        System.out.println("Invalid file!") ;
       else {
         int MAXSIZE = Kernel32.GetFileSize (filehandle, null);
         byte[] filedata = new byte[MAXSIZE] ;
         int trycount = MAXSIZE;
         int [] bytesread = {0} ;

         boolean readstatus = Kernel32.ReadFile( filehandle, filedata, trycount, bytesread, null) ;
         stop_t = System.currentTimeMillis() ;  // end time

         System.out.println("File size: " + MAXSIZE + "   bytesread: " + bytesread[0]) ;
         System.out.println("Time to read file into buffer (ms) : " + (stop_t-start_t)) ;
         Kernel32.CloseHandle(filehandle) ;    // close file right away
        }
   }
   
}


Inline Native Declarations Version


/* J/Direct Win32 Java application to read in file into buffer
   Uses inline native method declarations and structs.
    					M. Gallant  09/06/2000   */


import com.ms.win32.win;

class LoadFileToString {

   public static void main(String args[])
   {
     long start_t, stop_t ;
     SECURITY_ATTRIBUTES secatt = new SECURITY_ATTRIBUTES() ;

     System.out.println("Loading  " + args[0] + " into byte buffer ..... \n") ;
      start_t = System.currentTimeMillis() ;
      int filehandle = CreateFile(args[0], win.GENERIC_READ, win.FILE_SHARE_READ, secatt, 
                       win.OPEN_EXISTING, win.FILE_ATTRIBUTE_READONLY, 0) ;
      if(filehandle == win.INVALID_HANDLE_VALUE)
        System.out.println("Invalid file!") ;
       else {
         int MAXSIZE = GetFileSize (filehandle, null);
         byte[] filedata = new byte[MAXSIZE] ;
         int trycount = MAXSIZE;
         int [] bytesread = {0} ;

         boolean readstatus = ReadFile( filehandle, filedata, trycount, bytesread, null) ;
         stop_t = System.currentTimeMillis() ;  // end time
         System.out.println("File size: " + MAXSIZE + "   bytesread: " + bytesread[0]) ;
         System.out.println("Time to read file into buffer (ms) : " + (stop_t-start_t)) ;
         CloseHandle(filehandle) ;    // close file right away
         }
   }
   
   /** @dll.import("KERNEL32",auto) */
   public native static int GetFileSize (int hFile, int[] lpFileSizeHigh);


   /** @dll.import("KERNEL32", auto) */
   public native static int CreateFile (String lpFileName, 
      int dwDesiredAccess, int dwShareMode, SECURITY_ATTRIBUTES lpSecurityAttributes, 
      int dwCreationDisposition, int dwFlagsAndAttributes, 
      int hTemplateFile);

  /** @dll.import("KERNEL32",auto) */
   public native static boolean ReadFile (int hFile, Object lpBuffer, 
       int nNumberOfBytesToRead, int[] lpNumberOfBytesRead, 
       OVERLAPPED lpOverlapped);

  /** @dll.import("KERNEL32",auto) */
    public native static boolean CloseHandle (int hObject);
}



/** @dll.struct() */
class SECURITY_ATTRIBUTES {
        public int nLength = 12;
        public int lpSecurityDescriptor;
        public boolean bInheritHandle;
}

/** @dll.struct() */
class OVERLAPPED {
        public int Internal;
        public int InternalHigh;
        public int Offset;
        public int OffsetHigh;
        public int hEvent;
}