Super Prev Next

Class description


Super Prev Next

Class Structure

abstract public class Structure

To represent a native structure in Java, a structure — class extending the abstract class Structure, has to be defined. Instance variables of a structure (so-called reflecting fields) correspond to fields of the native structure (native fields). Primitive types, java.lang.String, subclasses of Structure and Callback, the class Pointer, arrays of the above types with any dimension are permitted among reflecting types (types of reflecting fields). The order of the reflecting fields is not important.

Valid reflecting types are defined in table 1. Reflecting types

Table 1. Reflecting types

native field’s C type (T) reflecting field’s Java type (T’)
char char
double double
float float
short short
int, long int
64-bit integer type long
struct Structure or its subclass
Type* Pointer
Type (*) (...) Callback or its subclass
char* java.lang.String
(zero-terminated)  
wchar_t* java.lang.String
(zero-terminated)  
Type[]...[] Type’[]...[]

A structure may also have any number of additional, non-reflecting instance fields of any type.

Notes:

  1. The default constructor has to be defined in a structure.
  2. Different structures should be used to represent different native structures.


Super Prev Next

defineLayout()

public abstract String defineLayout();

An implementation of this method in a structure completely defines the layout of the respective native structure. In fact, an implementing method simply returns a string containing a comma-separated enumeration of all native fields along with their types, and, optionally, alignment information. The order of enumeration has to exactly match that of native fields declaration, and all instances of a particular structure have to return exactly the same string.

The syntax of the return string is as follows:

    <layout>     ::= [<alignment>] <field>
                     {',' [<alignment>] <field>}
    <alignment>  ::= '#pack(' ( '1'| '2' | '4' | '8' | '16' ) ')'
    <field>      ::= <field-type> <field-id>
    <field-type> ::= <arg-type>{'['<length>']'}
    <arg-type>   ::= (<prim-type> |
                     'CSTRING' | 'UNICODESTRING' | 'BSTR' |
                     <full-struct-classname> |
                     <full-callback-classname>){'*'}
    <prim-type>  ::= 'int'|'long'|'short'|'char'|'float'|'double'

    <field-id>   - field identifier
    <length>     - positive integer

Table 2. Denoting native field types in defineLayout() return string describes the correspondence between types defined by the defineLayout() enumeration and those of native fields.

Table 2. Denoting native field types in defineLayout() return string

native field’s C type (T) defineLayout() type (T’)
char "char"
double "double"
float "float"
short "short"
int, long "int"
64-bit integer type "long"
struct structure full name
Type* "Type*"
Type (*) (...) callback full name
char* "CSTRING"
(zero terminated)  
wchar_t* "UNICODESTRING"
(zero terminated)  
BSTR "BSTR"
(Windows only)  
Type[i1]..[in] "Type’[i1]..[in]"

Note that the full name of a structure or callback (including package name) has to be used in <arg-type>. The defineLayout() return string may not contain field names absent among instance variables of the implementing class.

The default field alignment is 8 bytes for Windows version and 4 byte for Linux and Macintosh versions.

New in version 2.1:

The optional alignment clauses (#pack()) allow you to specify arbitrary field alignment. Just like “#pragma pack(N)” or a similar directive in C, “#pack(N)” encountered in a defineLayout() return string changes the alignment of subsequent fields to N bytes (N may be 1, 2, 4,8 or 16.)

See 2. Variably packed structure for an example featuring a variably aligned C structure.

Any attempt to use a malformed structure causes IllegalStructureException throwing at runtime.

A subtle thing with the reflection of types is that char* (wchar_t*) in C may denote two different entities:

  1. an arbitrary sequence of bytes (words); or
  2. C string — a zero-terminated sequence of characters (wide characters)

In the first case, the type char* (wchar_t*) should be specified in the defineLayout() return string, whereas in the last, CSTRING (UNICODESTRING) is appropriate.

Example:

    /* C */
    struct SomeStruct {char* name};

    /* Java */
    class SomeStruct extends Structure {
        String name;
        public SomeStruct() {}
        public String defineLayout(){
            return "CSTRING name";
        }
    }

All structures are NOT compatible even if their classes were defined identically:

Example:

    class Struct1 extends Structure{
        int x;
        String defineLayout(){return "int x";}
    }
    class Struct2 extends Structure{
        int x;
        String defineLayout(){return "int x";}}
    }
    ...
    Struct1 s = new Struct1();
    Argument a = Argument.create("Struct2",s);
    /* error: DifferentTypesException will be thrown here */

Figures 1. Structure containing an array and a pointer to the same structure. and 2. Variably packed structure illustrate the use of the class Structure.

Figure 1. Structure containing an array and a pointer to the same structure.

    /***** C *****/

    struct SomeStruct {
        int x;
        SomeStruct* next;
        int arr[2][5];
    };

    /***** Java *****/

    package pack1;

    class SomeStruct extends Structure {
        int       x;
        Pointer   next;
        int[][]   arr;

        public SomeStruct() {}

        public String defineLayout(){
            return "int x, pack1.SomeStruct* next, int[2][5] arr";
        }

        Object nonnativefield;
        void someMethod(){...}
        ....
    }

Figure 2. Variably packed structure

    /***** C *****/

    #pragma pack(1)
    typedef struct{
        char a;
        double b;
    #pragma pack(2)
        int c;
        char d;

    } PACKED_STRUCT;

    /***** Java *****/
    class PACKED_STRUCT extends Structure {

        char a;
        double b; 
        int c;
        char d;

        public String defineLayout() {
            return "#pack(1) char a, double b, #pack(2) int c, char d";
        }

        public PACKED_STRUCT() {}
}


Super Prev Next

Class Callback

abstract public class Callback

To simulate a callback (a Java method called from an external function), a class extending Callback should be introduced in your Java program. The class implements the defineSignature() method specifying type names of callback parameters, and contains the required callback method.

The restrictions for callbacks are as follows:


Super Prev Next

defineSignature()

public abstract String defineSignature();

An implementing method has to return a string, which defines callback’s name and signature (return value and parameter type names). All instances of a particular subclass of Callback must return exactly the same string.

The syntax of the return string is as follows:

    <ret-type> <function name>'('[<arg-type>{','<arg-type>}]')'

    <ret-type>  ::= 'void'|<prim-type>
    <arg-type>  ::= (<prim-type> |
                    'CSTRING' | 'UNICODESTRING' | 'BSTR' |
                    <full-struct-classname>) {'*'}
    <prim-type> ::= 'int'|'long'|'short'|'char'|'float'|'double'

Examples:

    "void foo1 (int, int*)"
    "int foo2 (myStruct, CSTRING)"

The string specifies callback signature in the form required by the calling function. For instance, if the external function passes a parameter with the char* type (meaning C string) to a callback, the callback’s signature string has to contain CSTRING as the parameter type name, whereas the parameter type of the implemented Java callback should be java.lang.String.

Example:

    class Point2 extends Structure {...}
    ...
    public class Foo extends Callback{
        public String defineSignature(){
            return "void foo(int**, CSTRING, Point2)";
        }
        public void foo(Pointer a1, String a2, Point2 a2){:}
    ...
    }

The following table defines the correspondence between Java callback argument types and those specified in defineSignature() return string:

defineSignature() type (T’) callback argument types (T)
"char" char
"double" double
"float" float
"short" short
"int" int
"long" long
Structure subclass full name Structure subclass
"Type*" Pointer
"CSTRING" java.lang.String
"UNICODESTRING" java.lang.String
"BSTR" java.lang.String
"Type’[i1]..[in]" Type[i1]..[in]

If one of the following conditions is fulfilled:

then any attempt to use such a Callback subclass causes DifferentTypesException throwing.


Super Prev Next

free()

public void free();

When an argument is created for a particular callback, the latter is pinned, i.e. it shall not be freed by the garbage collector even if there are no references to it. In addition, operating system resources (a thread and memory blocks) are allocated for the callback. The method free unpins the callback and frees the associated resources.

If no arguments have been created for a callback C, a call to C.free() shall have no effect.

Note: It is highly recommended to free a callback when you no longer need it to prevent resource leaks. However, it has to be done with extreme care: if you accidentally free a callback and then it is called, your program is likely to crash with some weird diagnostics.


Super Prev Next

Class Argument

public class Argument

The class is intended for passing and receiveing external function parameters of various types. Argument is a wrapper class for unification of Java language types (primitive types, string) and xFunction simulated types (Structure, Callback, Pointer). All xFunction methods invoking external functions receive arguments as parameters.


Super Prev Next

UNICODESTRING, CSTRING, BSTR

public static final int UNICODESTRING, CSTRING, BSTR;

These constants describe argument string format. UNICODESTRING defines a zero-terminated Unicode argument string, CSTRING defines a zero-terminated ASCII argument string, and BSTR defines a Windows-specific argument type BSTR defined as Unicode string with length.


Super Prev Next

Argument(primitive-type)

public Argument (primitive-type value);

Creates an argument of the primitive-type (any primitive type except byte may be used). Note that creating an argument of the char type causes the narrowing conversion of value from Unicode to ANSI. In order to pass a true Unicode character, a string argument should be used.


Super Prev Next

Argument(String, int)

public Argument (String str, int strType)
throws IllegalStringConversionException;

Creates an argument of an either string type. If the specified strType is not one of Argument.CSTRING, Argument.UNICODESTRING or Argument.BSTR, then IllegalStringConversionException will be thrown. A terminating null character is always appended to the string.

Example:

    ...
    Argument a1 = new Argument("A string",Argument.CSTRING);
    Argument a2 = new Argument("\u2297",Argument.UNICODESTRING);


Super Prev Next

Argument(String, int, int)

public Argument (String str, int strType, int bytes)
throws IllegalStringConversionException;

Creates an argument that is a string of the given strType and is at least bytes long. If the specified strType is not one of Argument.CSTRING, Argument.UNICODESTRING or Argument.BSTR, then IllegalStringConversionException will be thrown. bytes is first rounded up to a multiple of four and if the length of str in bytes is equal to or above the rounded value, the excessive characters, if any, shall be cut off and no null character shall be appended to the string.

This constructor should be used when it is required to pass a character buffer of a certain size as an argument, in particular, when it has to be passed to an output or input/output parameter.


Super Prev Next

Argument(Structure)

public Argument (Structure s)
throws IllegalStructureException;

Creates an argument from a structure.


Super Prev Next

Argument(Callback c)

public Argument (Callback c)
throws IllegalCallbackException;

Creates an argument from a callback.


Super Prev Next

create(String, Object)

public static Argument create(String type, Object initValue)
throws IllegalSignatureException, DifferentTypesException,
IllegalStringConversionException;

Creates an initialized argument of the type type. The string passed to the type parameter has the following syntax:

    <arg-type>  ::= (<prim-type> |
                    'CSTRING' | 'UNICODESTRING' | 'BSTR' |
                    <full-struct-classname> |
                    <full-callback-classname>){'*'}
    <prim-type> ::= 'int'|'long'|'short'|'char'|'float'|'double'

Valid classes of initValue are primitive type wrappers, java.lang.String, a Structure subclass, Callback, and an array. If the actual type of the initial value is incompatible with that declared by the type parameter, DifferentTypesException will be thrown.

Examples:

    ...
    Argument.create("int",new Integer(33))
    Argument.create("CSTRING","abcd")
    Argument.create("int**", new int[10][10]);
    ...
    class SomeStructure extends Structure {int x;...}
    SomeStructure param = new SomeStructure();
    param.x = 1;
    Argument.create("SomeStructure", param)


Super Prev Next

getValue()

public Object getValue() throws GettingPointerValueException;

Returns value of the argument. This method is typically used to obtain values of output parameters. The actual type of the return value depends on the type of entity from which the argument was created. It may be a primitive type wrapper, java.lang.String, or a Structure/Callback subclass.


Super Prev Next

createPointer()

public Pointer createPointer();

Creates a pointer to the argument (see below detailed description of pointers).


Super Prev Next

Class Pointer

public final class Pointer extends Argument

The Pointer class simulates pointer types. With its help, external function parameters (arguments) may be passed/received by reference. Thus, the only objects that pointers can refer to are arguments (instances of the Argument class). The value of the referred argument can be obtained using the Pointer.deref() method. Note that xFunction does NOT intentionally provide methods to obtain the pointer value itself. It is only possible to get the value of the argument available through a pointer.


Super Prev Next

NULL

public static final Pointer NULL;

Used to pass null pointers. Compatible with any other pointers of any type.

public boolean isNull();

Used to determine if pointer is NULL.


Super Prev Next

create(String)

public static Pointer create(String type)
throws IllegalSignatureException;

Creates and returns an uninitialized pointer to type. This method is intended to receive output parameters by reference. The syntax of the type string is the same as in the Argument.create method.


Super Prev Next

createPointerTo(primitive-type)

public static Pointer createPointerTo( primitive-type initVal );

Creates an argument of a primitive type, initializes it with initVal and then returns a pointer to that argument. The created pointer can be used to pass/receive primitive type parameters by reference.


Super Prev Next

createPointerTo(Structure)

public static Pointer createPointerTo( Structure initVal )
throws IllegalStructureException;

Creates an argument of a (simulated) Structure type, initializes it with initVal and then returns a pointer to the argument.

The createPointerTo methods provide a more convenient way of creating initialized pointers to arguments. These methods are equivalent to the following superposition:

    Pointer.createPointerTo(val) =
    ( new Argument(val) ).createPointer()


Super Prev Next

deref()

public Object deref() throws NullDereferenceException;

This method provides the dereference operation for pointers. Given its instance object, it returns the value of the referred object. The actual type of the return value is either a primitive type wrapper class, java.lang.String, a Structure subclass, or Pointer.

Note: If a pointer is created by the Pointer.create(String) method, an immediate call to deref() causes NullDereferenceException throwing. The same exception will be thrown if an external function returns a bad pointer.


Super Prev Next

createArray(int)

public Object createArray (int length)
throws NullDereferenceException, IllegalDimensionException;

Creates a length elements array of the pointer’s type objects. If length is less than or equal to zero, IllegalDimensionException will be thrown.


Super Prev Next

createArray(int[])

public Object createArray (int[] dimensions) throws NullDereferenceException, IllegalDimensionException;

Creates a multi-dimensional array of the pointer’s type objects with the specified dimensions. If one of dimensions values is less than or equal to zero, IllegalDimensionException will be thrown.

Note: if pointer’s type is primitive, the createArray methods return an array of the primitive type rather than an array of the primitive type wrapper.

Example:

    int[] arr = (Pointer)Argument.create(
                 "int*", new int[5])).createArray(5);


Super Prev Next

cast(String)

public Pointer cast(String type) throws IllegalSignatureException;

Given its instance object, creates another pointer with the same value but different type specified in the type parameter. The syntax of the parameter is

    <arg-type>'*'

Example:

    Pointer p = Pointer.NULL.cast("int**");


Super Prev Next

Class xFunction

public class xFunction

An instance of xFunction provides a way to invoke an external function.


Super Prev Next

xFunction(String,String)

public xFunction(String library, String signature)
throws LibraryNotFoundException, FunctionNotFoundException,
IllegalSignatureException;

Creates an object by means of that an external function can be invoked. The syntax of the signature parameter is as follows:

    <ret-type> <function name>'('[<arg-type>{','<arg-type>}]')'

    <ret-type>  ::= 'void'|<arg-type>
    <arg-type>  ::= (<prim-type> |
                    'CSTRING' | 'UNICODESTRING' | 'BSTR' |
                    <full-struct-classname>){'*'}
    <prim-type> ::= 'int'|'long'|'short'|'char'|'float'|'double'

Example:

    "void    foo1 (short, myPackage.Point2*)"
    "CSTRING foo2 (CSTRING)"

The following table gives the correspondence between types of external function parameters and those specified in the signature:

parameter’s C type (T) signature type (T’)
char "char"
double "double"
float "float"
short "short"
int "int"
8 byte integer type "long"
struct Structure subclass full name
Type* "Type*"
T (*) (...) Callback subclass full name
char* "CSTRING"
(zero terminated)  
wchar_t* "UNICODESTRING"
(zero terminated)  
BSTR "BSTR"
(Windows-specific)  
Type[i1]..[in] "Type’[i1]..[in]"

Note: In Windows version of the library, all external functions called via xFunction should have the "stdcall" or "cdecl" calling conventions.

Note: An external function name specified in the constructor should be the name exported from the DLL (shared library), that are often mangled.

Example:

Consider a C function prototype:

    __declspec(dllexport) void foo(int a);

MSVC would export that function as _foo@4.

If the signature parameter is syntactically malformed or a class, which full name is used in signature, is not defined, IllegalSignatureException will be thrown.


Super Prev Next

xFunction(int,String)

public xFunction(int address, String signature)
throws LibraryNotFoundException, FunctionNotFoundException,
IllegalSignatureException;

Since xFunction 2.17 you can create xFunction object using function address instead of library and function name. The syntax of the signature parameter is the same.

Example:

    /* C */
    __declspec(dllexport) int __stdcall bar() {
        return 7;
    }
    
    __declspec(dllexport) int __stdcall foo() {
        return (int)bar;
    }

    /* Java */
    xFunction f;
    f = new xFunction("t", "int _foo@0()");
    int addr = ((Integer)f.invoke()).intValue();
    f = new xFunction(addr, "int _foo@0()");
    System.out.println((Integer)f.invoke());


Super Prev Next

invoke() methods

public Object invoke()
throws WrongArgumentNumberException,
IncompatibleArgumentTypeException;

public Object invoke(Argument arg1)
throws WrongArgumentNumberException,
IncompatibleArgumentTypeException;

. . .

public Object invoke(Argument arg1,Argument arg2,
Argument arg3, Argument arg4, Argument arg5)

throws WrongArgumentNumberException,
IncompatibleArgumentTypeException;

public Object invoke(Argument[] args)
throws WrongArgumentNumberException,
IncompatibleArgumentTypeException;

An invoke method calls the external function. For your convenience, separate methods for calling functions with up to five parameters are provided. There is also an universal method, which accepts an array of arguments thus allowing you to call functions with an arbitrary number of parameters.

Pointer.NULL may be substituted as the actual parameter for any formal parameter of the Pointer class. Types of passed arguments must exactly match the signature of the external function being invoked, otherwise IncompatibleArgumentTypeException will be thrown. If the number of arguments passed to an invoke method differs from the number of parameters in the function signature, WrongArgumentNumberException will be thrown.

The invoke methods formally return java.lang.Object. The actual class of return value is defined in the following table:

signature return type class of returned object
"void" null is always returned
"char" java.lang.Char
"double" java.lang.Double
"float" java.lang.Float
"short" java.lang.Short
"int" java.lang.Integer
"long" java.lang.Long
Structure subclass name Structure subclass
"Type*" Pointer
Callback subclass name Callback subclass
"CSTRING" java.lang.String
"UNICODESTRING" java.lang.String
"BSTR" java.lang.String

Example:

"C":

    /* void f(short,Point2*);*/
    f(1,0);

"Java":

    xFunction f = new xFunction("somedll",
                                "void f(short,Point2*)");
    f.invoke(new Argument((short)0), Pointer.NULL);


Super Prev Next

Class xFunctionException

abstract public class xFunctionException extends Exception

All exceptions thrown by methods of the xFunction classes extend xFunctionException.