|
|
|||||||||||||||
A Simple ExampleExport the RNIGetCompatibleVersion method from your DLL. All RNI DLLs must export this method; otherwise, an UnsatisfiedLinkError exception is thrown when the method is called. This is a new requirement for the Microsoft VM for Java. Previous releases did not require this export. The following example shows how to export this method. #include "native.h"; // RNI declarations (part of Microsoft SDK for // Java) __declspec(dllexport) DWORD __cdecl RNIGetCompatibleVersion() { return RNIVER; } Another example is a simple Java class that performs a prime-number sieve. You perform 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, CountPrimes is declared native and the loadLibrary call is added in a static block to make sure the DLL that implements the API will be loaded. Use the Java Language Compiler from Microsoft (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, use msjavah to produce a header file used by the native code: msjavah Sieve Which will 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 is implemented. Since Sieve doesn't have any data members, ClassSieve only 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 that is implemented is 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 that is manipulated. Note One useful feature of msjavah is that primitive types (int, boolean, long, and so on) marked 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 several helpers from native.h to access to the data of the array (phFlags->body) and to query its length (obj_length(phFlags)). Next, a .def file to export this API is added: LIBRARY SieveDemo DESCRIPTION 'Native DLL for SieveDemo' EXPORTS Sieve_CountPrimes RNIGetCompatibleVersion Finally, build everything, and then copy the resulting DLL to the system directory and test it.
|
© 1998 Microsoft Corporation. All rights reserved. Terms of use. |