Using the Raw Native Interface Previous
Previous
Introduction
Introduction
Index
Index
Next
Next

A Simple Example

First it is important that you the export the RNIGetCompatibleVersion method from your DLL. All RNI DLLs must export this method; otherwise, an UnsatisfiedLinkError exception will be thrown when the method is called. This a new requirement for the Microsoft VM for Java. Previous releases did not require this export. This is shown below:


        #include "native.h";  // RNI declarations (part of Microsoft SDK for
                              // Java)

        __declspec(dllexport)
        DWORD __cdecl RNIGetCompatibleVersion()
        {
            return RNIVER;
        }

Now, say we have a simple Java class that performs a prime-number sieve. We want to do the calculation in C implemented in a DLL called SieveDemo.dll. In Java, the class might look like the following:

    class Sieve
    {
        native static int CountPrimes(byte[] abFlags);

       
        static
        {
            System.loadLibrary("SieveDemo");
        }
    }

Here, we declare CountPrimes to be native and add loadLibrary call in a static block to make sure the DLL that is going to implement the API will be loaded.

The next step is to use the Microsoft Java compiler (JVC) to compile this Java source into a class file with the following:

    jvc Sieve.java

    Microsoft (R) Visual J++ Compiler Version 1.00.XXXX
    Copyright (C) Microsoft Corp 1996. All rights reserved.

Next we use msjavah to produce a header file for use by the native code:

    msjavah Sieve

Which should look like the following:

	/* DO NOT EDIT THIS FILE - it is machine generated */
	#include <native.h>
	/* Header for class Sieve */
	
	#ifndef _Included_Sieve
	#define _Included_Sieve
	
	typedef struct ClassSieve {
	#pragma pack(push,1)
	    int32_t MSReserved;
	    char PAD;	/* ANSI C requires structures to have a least one member */
	#pragma pack(pop)
	} ClassSieve;
	#define HSieve ClassSieve
	
	#ifdef __cplusplus
	extern "C" {
	#endif
	__declspec(dllexport) long __cdecl Sieve_CountPrimes(struct HSieve *,HArrayOfByte *);
	#ifdef __cplusplus
	}
	#endif
	#endif

This header file defines a structure ClassSieve that represents the data members of Sieve and a declaration for the native API that we're going to implement. Since (in this example) Sieve doesn't have any data members, ClassSieve just contains some housekeeping fields. Native APIs are of the form Package_Class_Member(...) and since Sieve is not in an explicitly named package, the API we're going to implement is therefore Sieve_CountPrimes(). The first parameter to the API is the "this" pointer, which, for static functions, will always be NULL. The second parameter is the byte array we're going to manipulate.

Note One useful feature of msjavah is that primitive types (int, Boolean, long, and so on) marked as being static and final become #defines in the resulting header file, making it much easier to share constants.

Next, we implement the C we need:

    #include <varargs.h>
    #include <native.h>
    #include "Sieve.h"

    long cdecl Sieve_CountPrimes(struct HSieve *phThis, HArrayOfByte *phFlags)
    {
        unsigned long count = 0;
        unsigned long i;

        for (i = 0; i < obj_length(phFlags); i++)
            (phFlags->body)[i] = 1;

        for (i = 2; i < obj_length(phFlags); i++)
        {
            if ((phFlags->body)[i] != 0)
            {
                unsigned long k;
                for (k = i + i; k < obj_length(phFlags); k += i)
                    (phFlags->body)[k] = 0;

                count++;
            }
        }

        return count;
    }

This is a fairly standard implementation of a sieve with a couple of helpers from native.h to get access to the data of the array (phFlags->body) and to query its length (obj_length(phFlags)).

Next, we add a .def file to export this API:

    LIBRARY         SieveDemo
    DESCRIPTION     'Native DLL for SieveDemo'

    EXPORTS
    	Sieve_CountPrimes
    	RNIGetCompatibleVersion 

All that is left to do is build everything and copy the resulting DLL to the system directory and see if it works.

Top© 1997 Microsoft Corporation. All rights reserved. Legal Notices.