# JNIWrapper Programmer's Guide Version: 3.6.1 Last Updated: June 12, 2007 Copyright © 2002-2007 TeamDev Ltd. # Chapter 1. Introduction In the few years since its first release, the JavaTM programming language has grown immensely to become a popular platform. Many developers working on different platforms find their own advantages in using Java technology. One of them is, of course, the "write once, run anywhere" ability allowing developers to write software on one platform and run it on another. Sometimes, however, Java programs have to interact with native code. This is well justified for such reasons as performance, a lack of features for platform integration in the Java platform or the need of legacy software interoperability. To solve this problem, Java Native Interface (JNI) was introduced in the Java platform, allowing programmers to write native code pieces and integrate them into their Java programs. The main difficulty arising from such an approach is that native code is completely disjoint from Java code in terms of writing, browsing, debugging and maintenance. In this document, we are introducing JNIWrapperTM - the product that allows developers to interface native code while retaining full control of the application on the Java side at any level. ## 1.1. About This Guide This guide introduces JNIWrapperTM, describes its design goals, concepts and principles, provides the requirements for using the product as well as sufficient information you need to know before starting to work with the product. This document covers all platform versions of JNIWrapper. In cases where functions treat a particular platform in a specific way, or specific configuration settings are needed, these are marked accordingly. ## 1.2. New in This Version New in this version (3.0) of the Programmer's Guide: Added: Chapter 8. ## 1.3. Related Documents The documents provided on the Documents page at the JNIWrapper area at TeamDev site (http://www.teamdev.com) are intended to help you understand and effectively use of the JNIWrapper technology. To make your learning curve shorter and smoother, we suggest that you read the documentation in the following order: You can start with the current Programmer's Guide document describing the ideas and basics of the proposed software. If you plan to develop your own software effectively, proceed from this Programmer's Guide to JNIWrapper Tutorial, which provides step-by-step instructions with code samples. Each version of JNIWrapper is supplied with updated Release Notes. To receive the up-to-date version of specific information, be sure to check the Release Notes section inside `Readme.txt` file before installing JNIWrapper. You can also find helpful information in the Frequently Asked Questions document, which we regularly update based on the questions we get from our users. The document can be accessed online at the JNIWrapper site. ## 1.4. About JNIWrapper JavaTM is a very powerful platform allowing programmers to develop state-of-the-art software. It is, however, designed to run on a variety of different platforms and therefore does not include every feature of every platform. Certain basic things like creating a symbolic link under Linux or operating with registry items under Windows® are not supported in JavaTM. Programmers willing to do this are forced to write a native library and classes interfacing with it, then debug the code using two different debuggers (Java- and native-side). These are sometimes difficult and always very time-consuming tasks. All of them can be avoided by using JNIWrapper - a Java library for calling native library functions. With JNIWrapper, you can extensively use the potential of the underlying platform (like tray icons or custom shape splash screens) with only a single native library, having the full control over the program flow on the Java side. ### 1.4.1. Technical Advantages JNIWrapper has a number of technical advantages over the competitors. The most important of them are: Comprehensive native function invocation support JNIWrapper supports both `stdcall` and `cdecl` calling conventions and all complex C types including structures and unions. Callbacks are fully supported with any parameter and return types and both calling conventions. For unexpected cases, you can create your own types taking full control over parameter behavior. Automatic resource management All resources allocated by JNIWrapper components are released automatically when no longer required. You can treat JNIWrapper variables as ordinary objects that can be picked up by Java garbage collector. JNIWrapper objects are also safe with regard to finalizers: all resources are guaranteed to be available during finalization. High performance This has always been our priority. JNIWrapper has been specially tuned for performance, particularly in cases where large amounts of data are involved in the interactions. Minimum behind-the-scenes operation You should always be able to see and understand what is happening when they work with native-side data. This helps both to develop and debug complex interactions between Java and native code. The product is extensively used in the projects carried out by our company, which ensures its efficiency, reliability, future support, and improvement. ### 1.4.2. New in This Release For detailed information about the changes in the current version, check the `Readme.txt` inside the JNIWrapper package. The JNIWrapper changes history is also available online at: http://www.teamdev.com/jniwrapper/whats_new.jsf # Chapter 2. Getting Started ## 2.1. System Requirements The following are general requirements to run JNIWrapper on the following supported platforms: Windows OS: Windows 9x, Me, NT 4.0, 2000 and XP Java: Java 2 SDK/JRE 1.3.x and later. For CodeGen GUI, the preferred JDK is 1.4.2. or later. Linux OS: Red Hat Linux 7.2, 9.0; Mandrake Linux 9.1, 9.2, 10.0; Mandriva 2005 LE; WhiteBox Linux; Gentoo Linux (in general, all distros on kernel 2.4.x and kernel 2.6.x) Java: Java 2 SDK/JRE 1.4.x Mac OS X OS: Mac OS X 10.3 (Panther) and later Java: Java 2 SDK/JRE 1.4.x There are no specific memory or other hardware requirements for developing an application based on JNIWrapper. ### 2.1.1. Other Platforms Support for other platforms like Solaris and HP-UX is planned for the future. ## 2.2. Package Contents The JNIWrapper package consists of the following main files required for work: Library JAR file - `jniwrap-<version>.jar`, where <version> is the product version, for example "3.0". Native code library for Windows - `jniwrap.dll` for Linux - `libjniwrap.so` for Mac OS X - `libjniwrap.jnilib` License file `jniwrap.lic` All the files need to be placed in the appropriate locations. Please see the section "Configuring Software" for more details about the product installation instructions. The package may also contain other files providing some useful information for the you, for example the `Readme.txt` file. # Chapter 3. Configuring JNIWrapper JNIWrapper consists of three main files required for the software functioning: a JAR file, native code library, and a license file. The following sections describe where each file should be located. No other configuration is required. ## 3.1. Library JAR File The JNIWrapper JAR file should be located in the program class path. Due to the limitations of the Java native library loading mechanism, it is not recommended to load JNIWrapper in custom class loaders, unless you are sure that it will be loaded in only one such class loader. The library file can also be placed in the boot class path or in the extension directory of Java runtime, but this is not required. ## 3.2. Native Code Library The JNIWrapper native code library is loaded using the standard Java native code loading mechanism. There are no known problems with placing the native code library file on a mapped drive or even using it from the network share using a UNC path.
| Do not rename the library file, or else it will not be loaded.
Even though the native code library can be placed virtually anywhere, its actual location should be determined considering the fact that Java code must find the library to load. It can be placed somewhere within the program library search path (value of the `java.library.path` system property, which is by default equal to the value of the system variable PATH on Windows or LD_LIBRARY_PATH on Linux). Alternatively, you can add a search path to the default library loader used by JNIWrapper or even write a custom one that searches for native code in a predefined location. Using a default path may be preferable for development and library loader as a much better way for distributing a complete application. Since version 3.0 it is possible to keep native libraries within a JAR file. JNIWrapper will automatically locate and install a library on demand. You may want to install the native code library into the directories on the default system path, for example: on Windows - the root of Windows installation or Windows\System32 on Linux - <java_home>/lib/i386 or <java_home>/jre/lib/i386 on Mac OS X - /usr/lib Note that this requires having appropriate access rights on the Windows NT/2000/XP, Linux and Mac OS X systems. Installing the native code library by using this way may be convenient, but is not a required procedure. ## 3.3. License File Placing the license file is very simple: it should be located in the same folder where the native JNIWrapper library (`jniwrap.dll` file) resides.
| Do not rename the license file, or else it will not be recognized.
Also, there is one universal way for redistribution of the runtime license file. You will just need to save this file to your application's JAR file, into its `META-INF` subfolder. For example, if you have some application called `<application_name>.jar`, the `jniwrap.lic` file should be located in the following folder:
        <application_name>.jar
            \META-INF
                jniwrap.lic
You may appear to have several licenses for JNIWrapper for different platforms supported. In this case, you need to put all the license key files as described above but make sure there is no file name conflict. JNIWrapper accepts multiple license files named like shown below: `jniwrap.lic` `jniwrap.lic1` `jniwrap.lic2` `...` `jniwrap.lic999` # Chapter 4. Working with Native Libraries and Functions ## 4.1. Finding Native Libraries JNIWrapper accesses native libraries by name using library loaders. Library loaders are responsible for finding and loading a library by its name. You can use the supplied implementation of a path-based library loader or create your own. The latter approach requires implementation of the `com.jniwrapper.LibraryLoader` interface. This interface defines two methods: `findLibrary()` for finding a file containing the required library by name, and `loadLibrary()` for loading the library (by calling `System.load`), also by name. Suppose you have implemented a library loader called `MyLibraryLoader`. To make JNIWrapper look for the libraries using this loader, you can write something like this:
        Library.setDefaultLibraryLoader(new MyLibraryLoader());
Remember that the default loader specified this way is also used for loading the JNIWrapper native library. Alternatively, you may use a custom loader to load a specific library only:
        myLibrary.load(new MyLibraryLoader());
## 4.2. Using `DefaultLibraryLoader` JNIWrapper comes with a convenient default implementation of the `LibraryLoader` interface: `DefaultLibraryLoader`. It looks for the libraries in a set of directories (path). The initial search path includes all directories from the `java.library.path` system property. New directories can be added to the search path using the `addPath()` method.`DefaultLibraryLoader` is a singleton and is also the one JNIWrapper uses by default. If using the default path with some additions is sufficient, then adding directories to the search path is the only configuration needed. For example, if native libraries (or the JNIWrapper native code) are to be looked for in the `bin` directory relative to the program working directory, the following line should be added to the JNIWrapper initialization part of your program:
        DefaultLibraryLoader.getInstance().addPath("bin");
## 4.3. Loading Native Libraries Loading of libraries does not require special attention, if only one library loader is used, i.e. when the necessary library is found and loaded using the loader set by the `setDefaultLibraryLoader()` method (or an instance of the `DefaultLibraryLoader` class, which is the initial value of that property). If a custom library loader should be used, an explicit call to the library's `load()` method should be made before any function is loaded from that library. Take a look at these examples. Using one library loader:
        Library kernel32 = new Library("kernel32");
        // Use kernel32 here
Using a custom library loader:
        Library customLib = new Library("myCustomLib");
        LibraryLoader myCustomLoader = new MyCustomLibraryLoader();
        customLib.load(myCustomLoader);
        // Use customLib here
## 4.4. Getting Functions from a Native Library Functions are represented by instances of the `com.jniwrapper.Function` class. A function is always part of some library and therefore, cannot be instantiated on its own. To get a function from the library, the `getFunction()` method should be used. For example:
        Function getLastError = kernel32.getFunction("GetLastError");
Please note that some compilers may mangle function names to include argument types or sizes. This version of JNIWrapper performs search only by the exact name, not by mangled names. Therefore, if you need to invoke a function with such a name, you should specify the full mangled name. For example:
        Function myFunc = myLibrary.getFunction("_myFunc@4");
Most libraries, however, export nice unmangled names. You can find out an exported function name by using tools such as dumpbin or Dependency Checker. ### 4.4.1. Managing Library's Global Variables Some global variable called `_data` is declared in the native library. To find a global variable on the Win32 platform, we can use the following example:
    extern "C" __declspec (dllexport) int* _data = new int(123);
To retrieve a value of the variable in the library, we can use the `Library.getVariable()` method. The sample code below shows how it can be done:
     // load library
     Library SAMPLE_LIB = new Library("Library_Name");

     Int result = new Int();

     // get a variable pointer
     SAMPLE_LIB.getVariable("_data", new Pointer(result));

     // read a variable value
     long variableValue = result.getValue();
## 4.5. Calling Conventions There are two widespread calling conventions: `cdecl` used in most C/C++ programs and `stdcall` used, for example, in Pascal. Calling convention is a function property since a library can export functions that use different calling conventions. Use your library documentation to find out which calling convention is used by the functions you are going to invoke. ### 4.5.1. Calling Conventions on Windows Most Windows® API functions use the `stdcall` calling convention. This is the default convention used by JNIWrapper. If the function you need to call uses a different calling convention, you should set it in the function object. For example:
        cdeclFunction.setCallingConvention(Function.CDECL_CALLING_CONVENTION);
### 4.5.2. Calling Conventions on Linux/Mac OS X The majority of libraries on Linux use the `cdecl` calling convention. This is the default calling convention on Linux. # Chapter 5. Passing Parameters to/from Native Code In JNIWrapper, parameters are passed to and from native code using `com.jniwrapper.Parameter` objects. These objects behave like variables of different types depending on the actual subclass used. All parameters are mutable, which means that you can change any value at any time. All parameters can be shared across function calls, i.e. one can pass the result of one function call directly to another without creating a new object. ## 5.1. Primitive Types JNIWrapper provides parameter classes for all the primitive types available in the native program: signed and unsigned integers of different sizes, floating point values, single-byte and wide characters, etc. Related types usually have a common superclass or implement a common interface. All simple types have a no-argument constructor that initializes a parameter to the default value (usually zero or equivalent), a constructor with the initial value and a copying constructor. They also have appropriately typed `getValue()` and `setValue()` methods. Take a look at the example of using the `DoubleFloat` parameter:
        DoubleFloat d1 = new DoubleFloat(1.2345);
        DoubleFloat d2 = new DoubleFloat(d1);
        d1.setValue(9.876);
        System.out.println(d2.getValue());
### 5.1.1. Mappings of Native Types to JNIWrapper Classes Below is given a table of the mappings for most commonly used data types along with some comments. For more information, visit http://www.teamdev.com/jniwrapper/nativeTypes.jsf Table 5-1. Mappings of Native Types to JNIWrapper Classes
Native Type (C/C++) | JNIWrapper type | Comments
--- | --- | ---
Boolean Types
`bool` | `Bool(1 byte), IntBool(4 bytes)` |
Character Types
`char` | `Char` |
`wchar_t` | `WideChar` |
`uchar *` | `Char, UInt8` |
Integer Types
`short` | `ShortInt` | The unsigned types are represented by prefixing U to the type name. For example, the unsigned `int` (or unsigned) type is `UInt`.
`int` | `Int` | There are also types for predefined-width integers: `Int8`, `Int16`, `Int32` and `Int64`, they also have the unsigned variants.
`long` | `LongInt` |
Floating-point Types
`float` | `SingleFloat` |
`double` | `DoubleFloat` |
`long double` | `LongDouble` | Long double is the same as double (8-byte floating-point value) on the Win32 platform.
Pointer Types (not arrays)
`void *` | `Pointer.Void` |
`const` | `Pointer.Const` | Use `Pointer.Const` if the referenced object is not to be modified by the calling function.
`type *` | `Pointer` | To create a pointer to the value (variable) of a known type, use the `Pointer` class. For example: `int *i;` is `Pointer i = new Pointer(new Int());`
`type *` | `Pointer.OutOnly` | Use `Pointer.OutOnly` if the referenced object is not to be read by the calling function.
`char *` | `AnsiString` |
`wchar_t *` | `WideString` |
Arrays
`<c primitive type>[n]` | `PrimitiveArray(<corresponding JNIWrapper type>.class, n);` |
#### 5.1.1.1. Mappings for Windows API Types Windows API includes many data types which are not listed here (for example, DWORD, HANDLE). If you need to use one of such types, use Windows-specific documentation such as MSDN to find out the actual C type that corresponds to it (for example, LPSTR corresponds to char*), and use the relevant JNIWrapper type for the argument. You can also check the online Windows Data Types table available at http://www.teamdev.com/winpack/windowsTypes.jsf ## 5.2. Structures and Unions JNIWrapper supports C-like structures and unions. Like in C, the structure and union definitions are similar. Both provide a constructor that takes an array of parameters defining the structure or union contents. If you want to create a reusable Java class for a structure or unions, you can use a protected no-argument constructor and initialize the content by calling the `init` method. This method is provided for convenience, because class fields are initialized after the superclass constructor is invoked and therefore, cannot be used as constructor arguments. The structure and union member values are accessed by directly querying the parameters specified in the constructor for their values. For example:
    /*
    Structure definition in C:
    struct SomeStruct
    {
            int a;
            char b;
            double c;
    }
    */
    Int intField = new Int();
    Char charField = new Char();
    DoubleFloat doubleField = new DoubleFloat();

    struct = new Structure(new Parameter[] {intField, charField, doubleField});
    doubleField.setValue(10); // set struct.a value to 10
    // invoke some code that modifies the structure here
    System.out.println(doubleField); // prints new value of struct.c
To learn how to use linked structures, open: `<jniwrapper-3.x-win32.zip>/samples/src/LinkedStructureSample.java` ### 5.2.1. Setting Structure Alignment Structures can be defined with different alignments. The structure alignment is specified in the constructor (or in the call to the `init` method). Here is the example of a reusable structure definition that supports different alignments:
    private static class TestStruct extends Structure {
        public Int _int = new Int();
        public Int8 _int8 = new Int8();
        public Int16 _int16 = new Int16();
        public Int32 _int32 = new Int32();
        public Int64 _int64 = new Int64();
        public LongInt _long = new LongInt();

        public TestStruct() {
            init(new Parameter[] {
                _int, _int8, _int16, _int32, _int64, _long
            });
        }

        public TestStruct(short alignment) {
            init(new Parameter[] {
                    _int, _int8, _int16, _int32, _int64, _long
                }, alignment);
        }
    }
### 5.2.2. Setting an Active Union Member Unlike C, in JNIWrapper you need to define the active union member explicitly using the`setActiveMember()` method. However, this can be done after the function call where the union data was modified. Take a look at the following examples of the union usage:
    union = new Union(new Parameter[] {intField, charField, stringField, structField});
    union.setActiveMember(stringField);
    stringField.setValue(STRING_VALUE);
    func1.invoke(result, union);
    // ...
    func2.invoke(union, (Parameter[])null);
    union.setActiveMember(structField, true);
    assertEquals(X_VALUE, structField.getX());
Structures and unions can consist of any simple or complex members that are JNIWrapper parameters. In the above example, one of the union members is a structure. ## 5.3. Pointers JNIWrapper supports C-like pointers to all the defined types. You can create a pointer by instantiating the `com.jniwrapper.Pointer` class. Pointers should always refer to some object. For example:
    Pointer pInt = new Pointer(new Int());
A pointer automatically allocates memory for its referenced object; it handles reads and writes requiring the referenced object to read or write its data when the pointer itself is read or written. Thus, after any native function call, all the parameters are updated even if they are referenced by several nested pointers. For example:
    Int value = new Int();
    Pointer ppInt = new Pointer(new Pointer(value));

    // invoke func(int **i) passing ppInt as a parameter
    func.invoke(null, ppInt);
    System.out.println(value) // value is updated!
In cases where the referenced object is read-only or write-only, one can use the `Pointer.Const` or `Pointer. OutOnly` types, respectively. Note, however, that using these classes cannot enforce the read-only or write-only policy on the native function which may still access the data inappropriately. It is recommended that these classes are only used for performance improvements. JNIWrapper supports pointers that refer to undefined values (`void*` in C) through the `Pointer.Void` class. Use this class when you do not care about the actual referenced object and do not need to allocate the memory a pointer points to. For example, if you need a constant `(HWND)-1` you can use the following construct:
    Pointer.Void HWND_TOPMOST = new Pointer.Void(-1);
`Pointer.Void` is not a pointer. It doesn't have a referenced object and it is not assignable to and from any other kind of pointer. The name of the type only reflects the fact that this parameter always has the same size as a platform-dependent pointer. ### 5.3.1. Function Pointers Another capability of the `Pointer.Void` class is that it can also be used to represent a function pointer and to call the function it points to. The `asFunction()` method returns a function object that can be used to invoke a function that a given pointer points to. Consider the following example. A native library provides a function to install a callback that returns an old callback function pointer:
    typedef void (*PCallbackType)(int);
    PCallbackType installCallback(PCallbackType);
One can install a hook to monitor the callback invocation in the following way:
    // Field declaration
    Pointer.Void myOldCallback;
    // ...
    // Callback installation code
    installCallback.invoke(myOldCallback, new HookCallback());
and later inside the `HookCallback` class:
    protected void callback() {
        // do some hook stuff
        myOldCallback.asFunction().invoke(null, intParam);
    }
To create an object callable from native code, use the `Callback` class. ### 5.3.2. ArithmeticalPointer Class Limited pointer arithmetics is supported through the `ArithmeticalPointer` class. This pointer also manages one referenced object, but also accommodates an offset from its initial value. Such a pointer can be used for passing to the functions such as `strtok` that offset a pointer to iterate through data. Note that the referenced object cannot be changed and is always read and written at its initial offset. ### 5.3.3. Casting Pointers A typed pointer represented by an instance of the `Pointer` class can be cast to an un-typed (i.e. void) pointer represented by an instance of the `Pointer.Void` class and vice versa. The following code demonstrates casting the instance of the `Pointer.Void` class to the instance of the `Pointer` class:
      // retrieve the pointer somewhere
      Pointer.Void handle = getHandle();

      // prepare the data pointer, assuming that it points to an integer value
      Int data = new Int();
      Pointer dataPtr = new Pointer(data);

      // cast the pointers
      handle.asTypedPointer(dataPtr);
After the last operation, the `data` variable obtains the value which the `handle` pointer points to. Casting an instance of the `Pointer` class to an instance of the `Pointer.Void` class is done as shown on the sample below:
      // create typed pointer
      Int data = new Int(123);
      Pointer dataPtr = new Pointer(data);

      // create void pointer
      Pointer.Void handle = new Pointer.Void();

      // cast the pointers
      dataPtr.asVoidPointer(handle);
After the last operation, the `handle` pointer will have the same address as the `dataPtr` pointer. ## 5.4. Arrays JNIWrapper supports two types of arrays: Primitive arrays that are made up of primitive values, such as integers or characters. Complex arrays that can consist of elements of any implemented type. You can use complex arrays to store primitive values, but the primitive arrays are more efficient for this purpose. Arrays are represented by the instance of `com.jniwrapper.PrimitiveArray` and `com.jniwrapper.ComplexArray` for the primitive and complex arrays, respectively. Arrays are represented by `PrimitiveArray` and `ComplexArray` types parametrized by parameters that represent the actual type. For example:
    int i[10];
is
    PrimitiveArray i = new PrimitiveArray(Int.class, 10);
The main difference between the two types of arrays is that a primitive array is a plain data block that contains sequential data of a given type, while a complex array is a sequential storage of elements of any complexity that are all read and written whenever an array is read or written, respectively. This means that an array of pointers cannot be implemented as a primitive array because the referenced objects will not be written or read when needed. `PrimitiveArray` can be only of primitive types (`int`, `char`, `float`) and not of arrays, pointers, structures, etc. `ComplexArray` has no restriction on its element type. Sometimes arrays can be specified as pointers in function signature, for example:
    void foo(int *arg);
But if the actual value is a pointer to some number of integers, use array as a parameter. The simplest method of creating an array is using a constructor specifying a sample parameter and array size. Note that the array's member type should be correctly cloneable. For example, to create an array of bytes, you can use the following construct:
    PrimitiveArray val = new PrimitiveArray(new Int8(), 256);
Another method of creating an array is using a Java array of parameters that should constitute it. This is achieved by using a constructor taking a `Parameter[]` argument. Both primitive and complex arrays can be created this way. Here is an example of creating an array of pointers to integers:
    Parameter[] members = new Parameter[10];
    for(int i = 0; i < 10; i++) {
            members[i] = new Pointer(new Int(i));
    }
    ComplexArray result = new ComplexArray(members);
### 5.4.1. Pointers to Array Contents When using arrays you should always remember that sometimes arrays are stored or passed to functions not as plain data, but as a pointer to the array contents. The most typical case is when an array argument or member is defined as a pointer to type (e.g. `double*`). In this case, the actual passed parameter should be a `Pointer`. For example:
    /*
    C declaration:
    struct s
    {
            int size;
            double *data;
    }
    */
    Int intMember = new Int(50);
    PrimitiveArray arrayMember = new PrimitiveArray(DoubleFloat.class, 50);
    Structure s = new Structure(new Parameter[] {intMember,
            new Pointer(arrayMember)});
If in the previous example, the second member is declared as `double data[50]` (predefined size array), the pointer wrapper should not be used. The same rule applies for passing arrays to a function call. For example:
     /*
     C declaration:
     double foo(double* data, int elementsCount);
     */

     Function foo = library.getFunction("foo");
     DoubleFloat result = new DoubleFloat();
     int count = 50;
     PrimitiveArray array = new PrimitiveArray(DoubleFloat.class, count);
     foo.invoke(result, new Pointer(array), new Int(count);
### 5.4.2. Controlling Memory Allocation for Arrays In most cases, the array sizes are known or may be computed before a call is made. There are cases, however, when defining an array size before a function call is not possible or not efficient. In these cases, the array that is passed by a pointer is either resized to accommodate all the data or allocated altogether by the callee. In the first case, the caller is usually still responsible for memory deallocation, while in the second case, the memory management is most likely the responsibility of the callee. The common thing in both cases is that the called function returns the new size of the array as one of the results of the call. JNIWrapper supports both ways of required memory management by using special array pointers - `ResizingPointer` and `ExternalArrayPointer`. Each of these pointers does not read the array it points to after the function call. The array should be read after the call is complete using the `readArray(int count)` method of the pointer. For example:
    PrimitiveArray myArray = new PrimitiveArray(Int8.class, length);

    Int16 len = new Int16(length);
    ResizingPointer pArray = new ResizingPointer( myArray);;
    Function func = getFunction("myFunction");
    func.invoke(null, pArray, new Pointer(len));

    length = (short)len.getValue();
    pArray.readArray(length);
    // use myArray here
The rule of thumb for choosing the correct pointer is as follows: if you want JNIWrapper to manage the memory allocated for the array, use `ResizingPointer`; if you do not need the memory management for the array memory, use `ExternalArrayPointer`. ## 5.5. Strings Strings in JNIWrapper are character arrays of a predefined size with convenience methods for getting and setting string values as zero terminated strings. JNIWrapper supports two types of strings: single-byte, or ANSI strings, and Unicode strings. All strings are defined with the maximum length that a string value can occupy. It is illegal to set a string parameter value to the value longer than its maximum length. Passing a string argument to a function that writes more data than is allocated may result in an error just like in the native programs. On the other hand, strings are safe in the way that the data is parsed until the terminating zero (of appropriate length) is found or the maximum string length is reached. Therefore, even a bad string without a terminating zero will not cause memory access failures in your program. Here are the examples of string usage:
    AnsiString s = new AnsiString("Hello, World!");
    WideString s2 = new WideString(20);
    s2.setValue("Goodbye, World!");
Similar to arrays, strings in native code can be both pointers to string data and character arrays themselves. When using strings as structure members, use the same guidelines to determine whether a pointer wrapper should be used. When passing strings as function arguments, however, strings are always passed as pointers and JNIWrapper does pointer wrapping automatically. You should remember though that wrapping is just a convenience feature and passing a `char**` will require creating a `new Pointer(new Pointer(new AnsiString()))`. ### 5.5.1. Str Class The `Str` class unifies different ways of working with native string data. Instances of the class work with ANSI or Unicode characters depending on the Unicode support available in the underlying operating system. If Unicode is supported, this class works as `WideString`, otherwise as `AnsiString`. You can also create `Str` instances that work specifically with ANSI or Unicode. Using this class would give the code that is easier to read, refactor and maintain. ### 5.5.2. StringArray Class The `StringArray` class provides functionality for working with native double zero terminated string data. When not explicitly defined, the type of characters depends on the Unicode support of an operating system under which the code is being executed. To set the required character type, use the `StringArray(boolean unicode)` constructor. ## 5.6. Enumerations A C enumeration type (for example `enum a {first, second, third}`) can be substituted by an integer parameter, for example `Int` class (or any other integer parameter). In this case, new `Int(0)` corresponds to 'first', new `Int(1)` corresponds to 'second' and so on. # Chapter 6. Calling Native Functions Native functions are called using the `invoke()` method of the `Function` class. The arguments and return value are specified using variables of the `Parameter` type. There are several overloaded versions of the `invoke()` method, but the idea and argument structure is similar: the first argument is always a holder for the return value and the rest are arguments in the order they appear in the function declaration. When a function is called, all passed parameters are passed to it and then the return value is stored in its placeholder. It is allowed to pass `null` instead of the return value parameter, in which case it will be ignored, but it is allowed for primitive types only. Doing this when the return value is not of a primitive type may result in an error, because memory must be allocated by the function caller if the function return value is big and there is no way to allocate appropriate structure automatically without knowing the actual return value type. There are no restrictions on the argument or return value types as long as they are what a function expects. ## 6.1. Calling Conventions If you are going to use a calling convention that differs from the default one used by JNIWrapper, the calling convention must be set before a native function is first called. Failure to do so will result in an error. Here is a complete example of calling a function:
    Function sprintf =
            new Library("msvcrt").getFunction("sprintf");
    sprintf.setCallingConvention(
            Function.CDECL_CALLING_CONVENTION);
    AnsiString result_buffer = new AnsiString();
    sprintf.invoke(
            null,
            result_buffer,
            new AnsiString("Hello, %s!"),
            new AnsiString("World"));
    System.out.println("result = " + result_buffer.getValue());
    //Output: result = Hello, World!
This example shows that there is no problem with calling functions even with variable argument number. JNIWrapper checks that stack is left in consistent state after the function is called and handles most of the failures by throwing a Java exception. All exceptions descend from `com.jniwrapper.FunctionExecutionException`. These error or information messages from JNIWrapper can be disabled by adding the special category for JNIWrapper classes to your `log4j` configuration file:
    log4j.category.com.jniwrapper=FATAL
Also, it can be configured programmatically:
    Category jniwrapper = Category.getInstance("com.jniwrapper");
    jniwrapper.setLevel(Level.FATAL);
### 6.1.1. A Quick Way to Call a Function The `Function` class provides a shortcut way to call a function from a library without creating `Library` and `Function` instances: the `call()` method. To use it, write the following: Table 6-1.
    Function.call("user32.dll", "MessageBeep", retVal, new UInt(1));
    Function.call("/lib/libc.so.6", "printf", null, new AnsiString("Hello, World!\n"));
    Function.call("/usr/lib/libSystem.dylib", "printf", null, new AnsiString("Hello, World!\n"));
This will load a library using the default loader, look up a function and invoke it using the default calling convention. It is not recommended to use the `call()` method when your program makes a lot of native function calls, because it is more resource intensive. However, it is perfectly fine to use it in simple cases like getting the current directory. ## 6.2. Using Callbacks Callback is a user-defined function that is called by the library code at the appropriate time. Callbacks can have arguments and return a value. JNIWrapper supports callbacks with any kind of arguments and return values, as well as `stdcall` and `cdecl` calling conventions. Callbacks are represented by subclasses of the `com.jniwrapper.Callback` class. Passing a callback as an argument is no different from passing any other value: you just need to put an instance of the `Callback` class as the corresponding argument. For example: Table 6-2.
    final class EnumWindowsProc extends Callback
    // ...
    EnumWindowsProc enumWindowsProc = new EnumWindowsProc();
    Function.call("user32.dll", "EnumWindows", retVal,
    enumWindowsProc, new Int32(57));
    class MyComparator extends Callback
    // ...
    Function.call("/lib/libc.so.6", "qsort", null,
    dataPointer, new Int(size), new Int(memberLen), new MyComparator());
    class MyComparator extends Callback
    // ...
    Function.call("/usr/lib/libSystem.dylib", "qsort", null,
    dataPointer, new Int(size), new Int(memberLen), new MyComparator());
When a callback is no longer needed, you should explicitly free the resources associated with it by invoking its `dispose()` method. This is the only case in JNIWrapper where resources are to be explicitly freed, because some types of the callback objects may have no references from code and still be active, for example a window procedure callback instance may be created once when the window class is registered and remain active during the entire program lifecycle. To implement a callback, you need to subclass the `Callback` class implementing the `callback()` abstract method. The callback arguments and return value are specified in the constructor (by calling either the superclass constructor with parameters or `init()` method). The order of parameters is following: first go the arguments of a callback, and then a return value. Calling convention should also be set in the constructor if it is different from the default one . When the `callback()` method is invoked, argument parameters contain the values of the passed arguments; after the `callback()` method is complete, the value of the return value parameter is returned to the caller. Here is an example of a callback that takes an integer argument and returns its value incremented by one:
    /*
    C callback declaration:
    int callback(int);
    */
    private static class IncIntCallback extends Callback {
        private Int _arg = new Int();
        private Int _result = new Int();

        public IncIntCallback() {
            init(new Parameter[] {_arg}, _result);
        }

        public void callback() {
            _result.setValue(_arg.getValue() + 1);
        }
    }
# Chapter 7. Working with Multithreading JNIWrapper was designed with threading in mind and is already successfully used in a multithreaded environment. The following sections describe JNIWrapper components in terms of thread safety. ## 7.1. Parameters Parameters in JNIWrapper are not synchronized because synchronizing at this level is very inefficient, and performance was a high-priority goal in JNIWrapper development. Therefore, access to the parameter data should be enclosed in synchronization blocks if there is a possibility for more than one thread to access the data at a time. If you have only one parameter that is shared between threads, you can synchronize on that object's monitor:
    Int32 sharedInt = new Int32();
    // ...
    // First thread
    synchronized(sharedInt) {
        someFunction.invoke(sharedInt);
    }
    // ...
    // Second thread
    synchronized(sharedInt) {
        if (sharedInt.getValue() == 10)
            System.out.println("Value is set to 10");
    // ...
## 7.2. Functions Function invocation in JNIWrapper is completely thread-safe. If the called function is thread-safe, any number of threads may invoke it concurrently at any time. No synchronization is required and/or performed, and calls are executed fully concurrently as if invoking simple Java methods. # Chapter 8. Code Generator for JNIWrapper In the new version of JNIWrapper 3.0 we have added a new Code Generator application. Its main goal is to provide a convenient and efficient way to generate Java wrappers for custom C types such as structures, unions, callbacks, etc. ## 8.1. Overview The Code Generator for JNIWrapper allows you to select C code containing the required C types and generate the corresponding Java wrappers for them. This code can be either in a C header file or in a fragment of code, which can be inserted from the clipboard or just typed as text. The resulting Java classes (Java wrappers for C types) are saved to the specified folder. ## 8.2. Running Code Generator for JNIWrapper The application can be started by the appropriate file from the `bin` directory of JNIWrapper installation. The table below shows what file should be executed (depending on the platform) to start the applicaiton: Table 8-1.
    Codegen.bat
    Codegen-linux.sh
    Codegen-macosx.sh
This application does not provide command-line mode. ## 8.3. Specifying Input Parameters and Options The application provides an ability to specify various options for code generation. These options can be divided into the following three categories: Input parameters specify the input C source code in which the necessary types are defined. It can be a C header file, a folder that contains C headers files or a fragment of C code. Generation parameters specify the set of types to generate wrappers for, their names and base types respectively. Output parameters specify the destination folder to save all generated Java files to and the root package name for all generated classes. ## 8.4. Using Type Replacement Table The Code Generator application imports all types that are defined in the specified source and builds a correspondence table: every imported C type is mapped to the corresponding type from the JNIWrapper library. The application provides an ability to change the name of a particular type as well as its base type (the parent type from the JNIWrapper library), in case this type was not recognized by the C parser. Also, it is possible to define a set of types to be generated: you can just select the necessary types in the appropriate table. ## 8.5. Namespaces and Package Naming The destination root package (which can be specified in the options) is actually a root for other subpackages automatically generated by the application. Also, it is possible to give a custom package name to each type (resulting class) individually. ## 8.6. Supported Types The current version of the application supports the following C types: `struct` `union` `callback` `enum` types that are defined or redefined using the `typedef` keyword Also, the application supports generation of pointers and arrays. ## 8.7. Known Limitations The current version of the application does not recognize the following C preprocessor directives: `#include` `#define` `#if` `#error` The inline functions (for example "void GetData() { return;}" should not be present in the C code either. Nester pointer types (for example: typedef int** PPInt) are not supported yet and they are processed as usual single pointers. Also, please keep in mind that the application just parses the given C code, but does not validate it anyhow. Therefore, before giving some C code to this application, make sure that code is compilable and valid. To generate a more complete set of wrappers, we recommend you to precompile the input C code with a C-compiler first, and then give the resulting file to the Code Generator application. This step will help you eliminate all unresolved dependencies. ## 8.8. Example Suppose you need to create a wrapper for the following C structure:
    struct Sample {
      int a;
      float b;
    };
which is used in the following C function:
    void sample(Sample* structure);
The Code Generator application will generate the following `Sample.java` wrapper for this C structure:
    public class Sample extends Structure {
      private Int _a = new Int();
      private SingleFloat _b = new SingleFloat();
      public Sample() {
        init(new Parameter[] {_a, _b});
      }
      ...
    }
Then, this generated `Sample.java` file should be included to the project and compiled. And the function call can be as follows:
    Library lib = ...; // library that contains 'sample' function
    Function sample = lib.getFunction("sample");
    Sample sample = new Sample();
    function.invoke(null, new Pointer(sample));
# Chapter 9. Using AWT Native Interface JavaTM includes the cross-platform standard windowing library called Abstract Window Toolkit(AWT). One of the design principles of the AWT was to include only the features that can be implemented on all platforms targeted for JavaTM. This imposed some limitations on the windowing interface features. To help you access the native controls that stand behind the AWT, the AWT native interface (JAWT) was introduced. JNIWrapper also supports this interface so that you don't need to write native code to access the JAWT features. ## 9.1. Using JAWT Support On the native side, all the JAWT functionality can be accessed through several structures defined in the `include/jawt.h` file in the JDK directory. The root structure - `JAWT` - is available from the `GetAWT` function. JNIWrapper provides the `com.jniwrapper.jawt.JAWT` class that implements all the functionality available through the JAWT structure. The `JAWT_DrawingSurface` and `JAWT_DrawingSurfaceInfo` classes correspond to the structures with the same names in the `jawt.h` file and provide the same functionality. ## 9.2. Accessing Native Control's Data The most common use of the JAWT interface is to get a handle of the native control that corresponds to a given component. This data is returned in the platform-dependent structure pointed to by the `platformInfo` member of the`jawt_DrawingSurfaceInfo` structure. The contents of this structure are defined in the `jawt_md.h` file in the `include/<platform>/` directory of the JDK installation. The correct structure needs to be passed to the constructor of the `JAWT_DrawingSurfaceInfo` class. A sample structure for Win32 is shown below:
    public class Win32DSI extends Structure
    {
        private Pointer.Void _handle = new Pointer.Void();
        private Pointer.Void _hdc = new Pointer.Void();
        private Pointer.Void _hpalette = new Pointer.Void();

        public Win32DSI()
        {
         init(new Parameter[]{_handle, _hdc, _hpalette},
                (short) 8);
        }
        /**
         * Returns target component handle (either window or
         * bitmap handle).
         */
        public Pointer.Void getHandle()
        {
            return _handle;
        }

        /**
         * Returns DC handle. This handle should be used for
         * drawing instead of handles returned * from
         * <code>GetDC</code> or <code>BeginPaint</code>.
         */
        public Pointer.Void getHdc()
        {
            return _hdc;
        }

        /**
         * Returns palette handle.
         */
        public Pointer.Void getHpalette()
        {
            return _hpalette;
        }
    }
## 9.3. Getting HWND of a Window Below is given an example of a code snippet that gets a Win32 window handle of an AWT window. It is very similar to the C-code required to do the same thing.
    JAWT_DrawingSurface ds = JAWT.getDrawingSurface(window);
    ds.lock();
    Win32DSI win32DSI = new Win32DSI();
    JAWT_DrawingSurfaceInfo dsi = new JAWT_DrawingSurfaceInfo(win32DSI);
    Pointer pDsi = new Pointer(dsi);
    ds.getDrawingSurfaceInfo(pDsi);
    int result = (int) win32DSI.getHandle().getValue();
    ds.freeDrawingSurfaceInfo(pDsi);
    ds.unlock();
    JAWT.freeDrawingSurface(ds);
    return result;
In the table below you can see how to create the wrappers for Java windows on different platforms: Table 9-1.
    // Using Wnd class from WinPack library
    JFrame window = new JFrame();
    window.setVisible(true); //a Java window should be visible
    Wnd wnd = new Wnd(window);
    // Using NSWindow class from MacPack library
    JFrame window = new JFrame();
    window.setVisible(true); // a Java window should be visible
    NSWindow wnd = new NSWindow(window);
## 9.4. JAWT Support in Different JDK Versions When programming using the JAWT interface, you should keep in mind that JAWT is a relatively new technology. It was introduced only in JDK 1.3 with limited functionality, has had many improvements in JDK 1.4, and JAWT is intended to completely replace such native-related functions as `sun.awt.windows. WToolkit.getNativeWindowHandleFromComponent`. For JDK 1.3, you should expect very limited support for JAWT. For example, the argument of the `getDrawingSurface()` method can only be a `java.awt.Canvas`. JDK 1.4 introduced new functions, such as AWT locking and unlocking, as well as extended the capabilities of the existing functions. # Chapter 10. Using JNIWrapper in Java Web Start Applications This section describes the way of deploying your applications that use JNIWrapper with the help of Java Web Start (JWS). One of the major requirements for any JWS application is that all its resources are located inside signed JAR files. Although JAR files can be signed multiple times, JWS does not accept files with more than one signature. It is also mandatory that all application JAR files are signed with the same signature. All JNIWrapper libraries are supplied already signed and signing them with a new signature makes them unacceptable for JWS. Fortunately, there is a simple solution. The main idea is to use the `<extension>` tag in the `.jnlp` file and to create two different `.jnlp` files for your application. One `.jnlp` file should contain your application files and the other - JNIWrapper resources. This technique is demonstrated in the example below. The first file is the application `.jnlp` file (`demo.jnlp`):
    <?xml version="1.0" encoding="utf-8"?>
    <jnlp spec="1.0+" codebase="http://www.teamdev.com/" href="demo.jnlp">
      <information>
        <title>WinPack Demo Application</title>
        <vendor>TeamDev Ltd.</vendor>
        <description>WinPack Demo Application</description>
        <description kind="short">The demo of WinPack library</description>
        <offline-allowed/>
      </information>
      <security>
          <all-permissions/>
      </security>
      <resources>
        <j2se version="1.3+" initial-heap-size="64m"/>
        <property name="sun.java2d.noddraw" value="true"/>
        <jar href="demo.jar"/><!-- demo.jar is your jar file signed with your own signature-->
        <extension name="jnw" href="jnw.jnlp"/>
      </resources>
      <component-desc/>
      <application-desc main-class="com.jniwrapper.win32.samples.demo.WinPackSet"/>
    </jnlp>
The `<extension>` tag above makes the reference to the other `jnw.jnlp` file which is declared in the following way:
    <?xml version="1.0" encoding="utf-8"?>
    <jnlp spec="1.0+" codebase="http://www.teamdev.com/" href="jnw.jnlp">
      <information>
        <title>JNIWrapper resources</title>
        <vendor>TeamDev Ltd.</vendor>
        <description>JNIWrapper Application</description>
        <description kind="short">JNIWrapper Application</description>
        <offline-allowed/>
      </information>
      <security>
          <all-permissions/>
      </security>
      <resources os="Windows">
        <nativelib href="jniwraplib.jar"/>
      </resources>
      <resources>
        <jar href="jniwrap.jar"/>
        <jar href="winpack.jar"/>
      </resources>
      <component-desc/>
    </jnlp>
The second `jnw.jnlp` file represents the JNIWrapper resource bundle for redistribution as part of another JWS application. The `jniwraplib.jar` package should only include one file:`jniwrap.dll`. After you've configured the `.jnlp` files, place them to your Web site and create a link to your main `.jnlp` file that will also download JNIWrapper resources by the reference.
| The license file for JNIWrapper should be placed to the `META-INF` folder of your application JAR file.
2. # Chapter 11. Using JNIWrapper in Applets To use JNIWrapper in applets, follow these instructions: Copy `jniwrap.dll` to the folder of a web server computer where the applet resides (it is recommended, but you can place `jniwrap.dll` to some other folder on the web server). Prepend the following code to the `init()` method of the applet:
       // passes the instance of the current object as parameter
       AppletHelper.getInstance().init(this);
   This call downloads `jniwrap.dll` from the web server and copies it to the Windows `system32` folder in the client's computer. The presence of `jniwrap.dll` on the client side is required, otherwise the applet will not work. If you copied `jniwrap.dll` to a folder with no residing applet, you should provide JNIWrapper library URL, for example:
       AppletHelper.getInstance().init("http://applets.com/native/jniwrap.dll");
3. Prepend the following code to the method to start the applet method:
       AppletHelper.getInstance().start();
4. This call starts NativeResourceCollector thread of JNIWrapper. Append the following code to the method to stop the applet method:
       AppletHelper.getInstance().stop();
This call stops NativeResourceCollector thread of JNIWrapper. The license file (`jniwrap.lic`) can be included into any JAR file of a JWS application, into the `META-INF` subfolder. `application.jar` should be signed and should reference the JNIWrapper library(s) in its manifest file by setting the class path variable. Signing JNIWrapper libraries is not necessary as they are already signed. The sample build file that prepares an applet library is shown below:
    <project name="Applet Sample" default="build" basedir=".">
     <property name="certificate" value=".keystore"/>
     <property name="licenseFile" value="jniwrap.lic"/>
     <property name="appletClasses" value="classes"/>
     <target name="build">
      <jar destfile="sample.jar">
       <fileset dir="${appletClasses}" includes="AppletSample.class"/>
       <manifest>
        <attribute name="Class-Path" value="jniwrap-2.5.jar"/>
       </manifest>
       <zipfileset file="${licenseFile}" prefix="META-INF" />
      </jar>
      <signjar jar="sample.jar" alias="your_alias" keystore="${certificate}"
                        storepass="your_storepass" keypass="your_keypass" />
     </target>
    </project>
Below is given the applet usage sample:
    <html>
    <body><h1>Applet Sample</h1>
    <p>
     <applet docbase="http://your_url" code="AppletSample.class" width="400" height="300" archive="sample.jar"/>
    </body>
    </html>
# Chapter 12. Using JNIWrapper in Native Executable Archives To demonstrate how to make a native executable file (which uses JNIWrapper) using JBuilderX "Archive Builder" utility, we have prepared the following algorithm: Remove all the signatures from JNIWrapper libraries you are going to use in your application. To do this, delete `JNIWRAPP.DSA` and `JNIWRAPP.SF` files from the `META-INF` subfolder in JNIWrapper JAR-libraries (such as `jniwrapper-3.0.jar`). This is necessary because "Archive Builder" does not correctly copy JAR's signatures and manifest files to the resulting archive. Copy the JNIWrapper runtime license file (j`niwrap.lic`) to the `META-INF` subfolder of the JNIWrapper library (for instance, `jniwrapper-3.0.jar\META-INF\`). Select the "Always include all classes and resources" option in the "Dependencies" section. This is necessary because "Archive Builder" does not correctly track the dependencies. Make an executable library. To run the created executable file, you need to place the `jniwrap.dll` library in the same folder. # Chapter 13. Using JNIWrapper in Servlets If you're going to use JNIWrapper in a web application, just place the `jniwrap.dll`, `jniwrap.lic` and `jniwrap.jar` files in the appropriate web server catalog within the program library search path. For example, if you use the Tomcat web server, you can place the files in:
    $TOMCAT_HOME/webapps/MyApp/WEB-INF/lib
but not in
    $TOMCAT_HOME/common/lib
Also, in a servlet you can add WEB-INF/lib directory to the path using the following code:
    DefaultLibraryLoader.getInstance().addPath(this.getServletContext().getRealPath("/") + "WEB-INF/lib");
# Chapter 14. Support If you have any problems or questions regarding JNIWrapper, please check the documents listed below. The answer to your question may already be there: Installation instructions Programmer's Guide Frequently Asked Questions (FAQ) page at: http://www.teamdev.com/jniwrapper/faq.jsf If none of the above resources contain the required information, please e-mail us at: jniwrapper-support@teamdev.com ## 14.1. Reporting Problems If you find any bugs, please submit the issue to us using a special report form on the TeamDev integrated customer support and troubleshooting center at: http://support.teamdev.com/forms/reportForm.jsf The form will help you provide all necessary information. ## 14.2. Troubleshooting To find a solution to your problem, please visit the Troubleshooting page at: http://www.teamdev.com/jniwrapper/tshoot.jsf This page is regularly updated using information from support requests. If you didn't find a solution, please e-mail us at jniwrapper-support@teamdev.com or report the problem as described in the previous section. # Chapter 15. Where to Get a New Version To get the latest version of JNIWrapper, please visit: http://www.teamdev.com/jniwrapper/downloads.jsf
| Copyright © 2002-2007 TeamDev Ltd. |