See:
Description
Java Native Access | |
---|---|
com.sun.jna | Provides simplified native library access. |
com.sun.jna.ptr | Provides various native pointer-to-type (<type> * ) representations. |
com.sun.jna.win32 | Provides type and function mappers required for standard APIs on the Windows platform. |
Examples | |
---|---|
com.sun.jna.examples | Various examples of library mappings and cross-platform feature implementations. |
com.sun.jna.examples.dnd | Cross-platform ghosted drag image implementation with demo application. |
Unix Examples | |
---|---|
com.sun.jna.examples.unix | Provides examples of *nix library mappings. |
Windows Examples | |
---|---|
com.sun.jna.examples.win32 | Provides examples of w32 library mappings. |
This document is the API specification for the JNA library for simplified native library access for Java.
// Alternative 1: interface-mapped class, dynamically load the C librarypublic interface CLibrary extends Library {CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);}// Alternative 2: direct-mapped classpublic class CLibrary {static {Native.register("c");}}
The String
passed to the Native.loadLibrary(String,Class)
(or NativeLibrary.getInstance(String)
) method is the undecorated name of the shared library file. Here are some examples of library name mappings.OS | Library Name | String |
Windows | user32.dll | user32 |
Linux | libX11.so | X11 |
Mac OS X | libm.dylib | m |
Mac OS X Framework | /System/Library/Frameworks/Carbon.framework/Carbon | Carbon |
Any Platform | <current process> | null |
Any given native library with a unique filesystem path is represented by a single instance of NativeLibrary
and obtained via NativeLibrary.getInstance(String)
. The native library will be unloaded when no longer referenced by any Java code.
If the library name is null
, your mappings will apply to the current process instead of a separately loaded library. This may help avoid conflicts if there are several incompatible versions of a library available.
The search path for loaded native libraries may be modified by setting jna.library.path
and a few other properties. See NativeLibrary
for details.
public interface CLibrary extends Library {int atol(String s);}
Alternatively, you can map directly to a declared native method:public class CLibrary {public static native int atol(String s);}
If you prefer to rename the Java methods to conform to Java coding conventions, then you can provide an entry (Library.OPTION_FUNCTION_MAPPER
/FunctionMapper
) in the options Map
passed to Native.loadLibrary()
which maps the Java names to the native names. While this keeps your Java code a little cleaner, the additional mapping of names may make it a little less obvious the native functions being called.An instance of the Function
class is obtained through the NativeLibrary
instance corresponding to the containing native library. This Function
instance handles argument marshalling and delegation to the native function.
C Type | Native Representation | Java Type |
char | 8-bit integer | byte |
wchar_t | platform-dependent | char |
short | 16-bit integer | short |
int | 32-bit integer | int |
int | boolean flag | boolean |
enum | enumeration type | int (usually) |
long long, __int64 | 64-bit integer | long |
float | 32-bit floating point | float |
double | 64-bit floating point | double |
pointer (e.g. void*) | platform-dependent (32- or 64-bit pointer to memory) | Buffer Pointer |
pointer (e.g. void*), array | 32- or 64-bit pointer to memory (argument/return) contiguous memory (struct member) | <P>[] (array of primitive type) |
In addition to the above types, which are supported at the native layer, the JNA Java library automatically handles the following types. All but NativeMapped and NativeLong are converted to Pointer before being passed to the native layer. | ||
long | platform-dependent (32- or 64-bit integer) | NativeLong |
const char* | NUL-terminated array (native encoding or jna.encoding ) | String |
const wchar_t* | NUL-terminated array (unicode) | WString |
char** | NULL-terminated array of C strings | String[] |
wchar_t** | NULL-terminated array of wide C strings | WString[] |
void** | NULL-terminated array of pointers | Pointer[] |
struct* struct | pointer to struct (argument or return) (or explicitly )struct by value (member of struct) ( or explicitly ) | Structure |
union | same as Structure | Union |
struct[] | array of structs, contiguous in memory | Structure[] |
void (*FP)() | function pointer (Java or native) | Callback |
pointer (<T> *) | same as Pointer | PointerType |
other | integer type | IntegerType |
other | custom mapping, depends on definition | NativeMapped |
NOTES
Buffer
in order to access a subset of the array (changing the effective size and/or offest). Memory
or Buffer
instead. NativeMapped
or supply type conversion information for the unsupported types. TypeMapper
for the Library.OPTION_TYPE_MAPPER
option when initializing a library interface. See W32APITypeMapper
for an example which provides custom conversion of boolean and String types. You are free to use whatever types are convenient in your defined interfaces, but all custom types must provide a mapping to one of the basic or derived types listed above. NativeMapped
interface. Structure
and Union
are not converted to Pointer
when passed by value. Memory
or Buffer
should be used instead (see Buffers).To map a native multi-dimensional array, use a single-dimensional Java array with a number of elements equivalent to the full native array, e.g.
// Original C code#define DIM0 2#define DIM1 3int array[DIM0][DIM1];int i,j;for (i=0;i < DIM0;i++) {for (j=0;j < DIM1;j++) {array[i][j] = i*DIM1 + j;}}// Equivalent JNA codefinal int DIM0 = 2;final int DIM1 = 3;int[] array = new int[6];for (int i=0;i < DIM0;i++) {for (int j=0;j < DIM1;j++) {array[i*DIM1 + j] = i*DIM1 + j;}}
Type-safe pointers may be defined by deriving from the PointerType
class. Any such user-defined type will be treated the same as a Pointer
.
String
s perform the same function as the native types const char*
and const wchar_t*
(NUL
-terminated arrays). In order to use the proper type when calling a native function, we have to introduce some sort of annotation to identify how the java String
should be converted. Java String
s are normally converted to char*
since this is the most common usage of strings. Strings are automatically converted to a NUL
-terminated array of char
across the function call. Returned char*
values are automatically copied into a String
if the method signature returns String
(strdup
, for example).If the native method returns char* and actually allocates memory, a return type of Pointer
should be used to avoid leaking the memory. It is then up to you to take the necessary steps to free the allocated memory.
When converting Java unicode characters into an array of char
, the default platform encoding is used, unless the system property jna.encoding
is set to a valid encoding. This property may be set to "UTF8", for example, to ensure all native strings use that encoding.
Arrays of String
passed to native code (either as a function argument or callback return value) will be converted into a NULL-terminated array of char*
(or wchar_t*
in the case of an array of WString
.
WString
class is used to identify wide character strings. Unicode values are copied directly from the Java char
array to a native wchar_t
array.Buffer
s may also be used as a memory buffer input argument; direct byte buffers can often provide much improved performance over primitive arrays. A pointer provided by native code may be converted to a Buffer
by calling Pointer.getByteBuffer(long, long)
.
If you need to pass in a subset of a primitive array, you can do so by wrapping it in a Buffer
subclass, such as ByteBuffer
, using the ByteBuffer.wrap(byte[],int,int)
method. Wrapping an array in a buffer also allows you to pass only a subset of a Java array to the native function.
Callback
interface, and define a single callback
method with a signature that matches the function pointer required by the native code. The name of the method may be something other than "callback" only if there is only a single method in the interface which extends Callback or the class which implements Callback
. The arguments and return value follow the same rules as for a direct function invocation.If the callback returns a String
or String[]
, the returned memory will be valid until the returned object is GC'd.
If your native code initializes function pointers within a struct, JNA will automatically generate an Callback
instance matching the declared type. This enables you to easily call the function supplied by native code using proper Java syntax.
// Original C codestruct _functions {int (*open)(const char*,int);int (*close)(int);};// Equivalent JNA mappingpublic class Functions extends Structure {public static interface OpenFunc extends Callback {int invoke(String name, int options);}public static interface CloseFunc extends Callback {int invoke(int fd);}public OpenFunc open;public CloseFunc close;}...Functions funcs = new Functions();lib.init(funcs);int fd = funcs.open.invoke("myfile", 0);funcs.close.invoke(fd);
Callbacks may also be used as return values. Native function pointers are wrapped in a proxy implementing the declared Callback type, to facilitate calling from Java.// Original C codetypedef void (*sig_t)(int);sig_t signal(int signal, sig_t sigfunc);// Equivalent JNA mappingpublic interface CLibrary extends Library {public interface SignalFunction extends Callback {void invoke(int signal);}SignalFunction signal(int signal, SignalFunction func);}
// Original C codeextern int printf(const char* fmt, ...);// Equivalent JNA mappinginterface CLibrary extends Library {int printf(String fmt, ...);}
Structure
represents a native struct
. By default, this type is treated as a pointer to structure (struct *
) on the native side when used as a parameter or return value. When used as a structure field, the structure is interpreted as by value. To force the complementary interpretation, the tagging interfaces Structure.ByValue
and Structure.ByReference
are provided.struct
s.// Original C codetypedef struct _Point {int x, y;} Point;Point* translate(Point* pt, int dx, int dy);// Equivalent JNA mappingclass Point extends Structure { public int x, y; }Point translate(Point pt, int x, int y);...Point pt = new Point();Point result = translate(pt, 100, 100);
Structure.ByValue
. Use the ByValue
class as the argument or return type.// Original C codetypedef struct _Point {int x, y;} Point;Point translate(Point pt, int dx, int dy);// Equivalent JNA mappingclass Point extends Structure {public static class ByValue extends Point implements Structure.ByValue { }public int x, y;}Point.ByValue translate(Point.ByValue pt, int x, int y);...Point.ByValue pt = new Point.ByValue();Point result = translate(pt, 100, 100);
// Original C codevoid get_devices(struct Device[], int size);// Equivalent JNA mappingint size = ...Device[] devices = new Device[size];lib.get_devices(devices, devices.length);
Alternatively, you can reallocate a single Structure instance into an array as follows:Device dev = new Device();// As an array of StructureStructure[] structs = dev.toArray(size);// As an array of DeviceDevice[] devices = (Device[])dev.toArray(size);
struct
Structure
of the appropriate type, then invoke Structure.toArray(int)
to convert to an array of initialized structures of the appropriate size. Note that your Structure
class must have a no-args constructor, and you are responsible for freeing the returned memory if applicable in whatever way is appropriate for the called function.// Original C codestruct Display* get_displays(int* pcount);void free_displays(struct Display* displays);// Equivalent JNA mappingDisplay get_displays(IntByReference pcount);void free_displays(Display[] displays);...IntByReference pcount = new IntByReference();Display d = lib.get_displays(pcount);Display[] displays = (Display[])d.toArray(pcount.getValue());...lib.free_displays(displays);
// Original C codetypedef struct _Point {int x, y;} Point;typedef struct _Line {Point start;Point end;} Line;// Equivalent JNA mappingclass Point extends Structure {public int x, y;}class Line extends Structure {public Point start;public Point end;}
Explicit initialization of nested structures is not required; the objects will be created as needed and properly mapped to the parent structure's memory.If you need a pointer to a structure within your structure, you can use the Structure.ByReference
tagging interface to indicate the field should be treated as a pointer instead of inlining the full structure.
// Original C codetypedef struct _Line2 {Point* p1;Point* p2;} Line2;// Equivalent JNA mappingclass Point extends Structure {public static class ByReference extends Point implements Structure.ByReference { }public int x, y;}class Line2 extends Structure {public Point.ByReference p1;public Point.ByReference p2;}
The more general case is just a pointer to memory. This allows you to define the field without necessarily defining the inner structure itself, similar to declaring a struct without defining it in C:// Original C codetypedef struct _Line2 {Point* p1;Point* p2;} Line2;// Equivalent JNA mappingclass Line2 extends Structure {public Pointer p1;public Pointer p2;}Line2 line2;Point p1, p2;...line2.p1 = p1.getPointer();line2.p2 = p2.getPointer();
typedef struct _Buffer {char buf1[32];char buf2[1024];} Buffer;class Buffer extends Structure {public byte[] buf1 = new byte[32];public byte[] buf2 = new byte[1024];}
Calculation of the native size of the structure is deferred until the structure is actually used.// Original C codetypedef struct _Header {int flags;int buf_length;char buffer[1];} Header;
require a constructor which establishes the required size for the structure and initializes things appropriately. For example:// Equivalent JNA mappingclass Header extends Structure {public int flags;public int buf_length;public byte[] buffer;public Header(int bufferSize) {buffer = new byte[bufferSize];buf_length = buffer.length;allocateMemory();}}
Structure
prior to a function call and read back from native memory after the function call. Sometimes a structure field is not intended for client use, gets modified asynchronously by hardware, or otherwise is effectively read-only. If you expect any fields of the structure to be modified by any agent outside your Java program, you should mark the field volatile
. This prevents JNA from automatically updating the native memory from the Java value. You can still force an update of the native memory from the Java value by calling Structure.writeField(String)
for the field in question.class Data extends com.sun.jna.Structure {public volatile int refCount;public int value;}...Data data = new Data();
In the above example, the field refCount
will only be written to native memory based on the Java value with a call to data.writeField("refCount")
. To obtain the current state of native memory, call Structure.read()
(to update the entire structure) or (to update just the refCount
field).Structure
's contents, you may mark its fields final
. Structure reads can still overwrite the values based on native memory contents, but no Java code will be able to modify any of the fields.class ReadOnly extends com.sun.jna.Structure {// Do not initialize the field here, or the compiler will inline the value!public final int refCount;{// Initialize fields here, to ensure the values are not inlinedrefCount = -1;read();// refCount might now have a different value}}...ReadOnly ro = new ReadOnly();// Will not compile!ro.refCount = 0;
Make certain you attend to the following:Union.setType(java.lang.Class)
method. On read, all non-pointer-based fields will be initialized from native memory. Structure, String, and WString members will not be initialized unless they are selected via Union.setType(java.lang.Class)
. errno
or GetLastError()
), the error code will be thrown as a LastErrorException
if you declare the exception in your JNA mapping. Alternatively, you can use Native.getLastError()
to retrieve it, providing that Native.setPreserveLastError(boolean)
has been called with a true
value. Throwing an exception is preferred since it has better performance. NativeMapped
, because it is generally unnecessary to use such objects and usually signals a programmer error. To avoid errors flagging the use of Java objects, use the library load option Library.OPTION_ALLOW_OBJECTS
with Boolean.TRUE.InvocationMapper
allows you to arbitrarily reconfigure the function invocation, including changing the method name and reordering, adding, or removing arguments. See the InvocationMapper
documentation for details.NativeLibrary.getGlobalVariableAddress(java.lang.String)
may be used to obtain the address of global variables as a Pointer
. Pointer methods may then be used to read or write the value as appropriate for the variable type.Native.setProtected(true)
. Not all platforms support this protection; if not, the value of Native.isProtected()
will remain false
.NOTE: When protected mode is enabled, you should make use of the jsig library, if available (see Signal Chaining) to avoid interfering with the JVM's use of signals. In short, set the environment variable LD_PRELOAD
(or LD_PRELOAD_64
) to the path to libjsig.so
in your JRE lib directory (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your Java application.
Structure.setAutoSynch(boolean)
with a false
parameter. It is then up to you to use Structure.readField(String)
and Structure.writeField(String)
or Structure.writeField(String,Object)
to synch with just the fields of interest.