This is a C link library and Java base class which can be used to help
implement libraries which use the Java Native Interface (JNI).
+It provides a base class for native objects which provides automatic
+(and manual) reclaimation, and a shared library for easy access to
+these and other JNI utilities.
+
Compile
-------
`bin/notzed.nativez/<target>/include' - header files
`bin/notzed.nativez/<target>/lib/libnativez.so' - linux shared library
`bin/modules/notzed.nativez/' - compiled class files
+`bin/notzed.nativez/<target>/bin/nativez-gen' - table generator
Usage
-----
Native Library
- - - - - - --
+Whilst not necessary one can use the native library for access to the
+NativeZ_* functions and some other cross-platform tools.
+
The native library should link with -lnativez and include "nativez.h".
Before using any functions invoke the nativez_OnLoad() function,
typically in the native library's JNI_OnLoad() function.
-Any instance of a class derived from NativeZ must be created using the
-NativeZ_* functions.
+Any instance of a class derived from NativeZ must be created or
+referenced using the NativeZ_* functions in order to partake of
+automatic cleanup.
Native functions should take object arguments and resolve them to
native pointers using NativeZ_getP().
The nativez_* functions are just general JNI and useful cross-platform
utility functions which may be freely used within (any) JNI code.
+See nativez.h for more information.
+
+nativez-gen
+-- - - - --
+
+nativez provides a couple of functions for compact table based
+resolution of shared library entry points from dynamically loaded
+libraries, and for resolving Java classes and field and method
+acccessors.
+
+Whilst the tables can be generated manually nativez-gen can be used to
+generate correct tables from a definition file. When run on a
+definition file it will create one or two pairs of static variables to
+be included in the C file that uses it.
+
+nativez-gen requires `perl' and the header section processing requires
+`cproto'.
+
+The definition file is made of any number of sections. Each section
+starts with a header which must be on the same line (including the
+`{') and a number of entries each on their own line followed by a `}'.
+Non-EOL whitespace is ignored. No quoting or escaping is available.
+
+See also `src/notzed.nativez/jni/nativez.gen'. It's dumb but somewhat
+messy perl.
+
+See also `src/notzed.nativez/jni/jni.make' for an example of how to
+invoke it automatically.
+
+java section
+- -- -- --
+
+Each entry must be on a separate line as below.
+
+java VarName com/package/name/ClassName {
+ static funcName, funcSig
+ funcName, funcSig
+ static fieldName,fieldSig
+ fieldName,fieldSig
+}
+
+VarName must be unique for each section in a single definition file.
+
+The *Name* and *Sig values are those passed to the corresponding JNI
+functions. The static modifier calls the *Static* variaants. A
+funcSig will contain a pair of parentheses and a fieldSig will not.
+
+For each java section the following definitions will be created:
+
+static struct {
+ jclass VarName_classid;
+ jmethodID funcName_[encodedSig];
+ jmethodID funcName_[encodedSig];
+ jfieldID fieldName_[encodedSig];
+ jfieldID fieldName_[encodedSig];
+} java;
+
+static const char *java_names =
+ "#com/package/name/ClassName\0"
+ ":funcName\0funcSig\0"
+ ".funcName\0funcSig\0"
+ ";fieldName\0fieldSig\0"
+ ",fieldName\0fieldSig\0"
+ ;
+
+encodedSig depends on the arguments to nativez-gen. By default for
+functions a compact variation of JNI name mangling is used where the
+primitive types are lowercased and any object types are converted to
+'l' with all [ collapsed to nothing. A longer option (--java-long) is
+somewhat similar but not (current) quite the same as the JNI name
+mangling and allows for overriden functions taking different object
+types in the same position.
+
+See the nativez-gen header for the rest of the options.
+
+header section
+ -- -- -- --
+
+A header section extracts prototypes from C .h header files and
+creates a typesafe structure of same.
+
+header libname path/header.h {
+ funcname_a
+ funcmame_b
+}
+
+libname is the name of the library as used in the
+nativez_ResolveLibraries() table. i.e. it's just a key and not the
+actual name.
+
+path/header.h should be the name as included directly in a C file,
+i.e. it can be used direclty in a #include directive. It is relative
+to the (-b path) command line argument.
+
+The contents of the section are just the function names required.
+
+All header sections in a definition file will be combined to create a
+pair of variables. If one assumes a second section for libname2 is in
+the file, this is an example output:
+
+#inclulde <path/header.h>
+#inclulde <path/header2.h>
+
+static struct {
+ /* libname */
+ type (*funcname_a)(args);
+ type (*funcname_b)(args);
+ /* libname2 */
+ type (*funcname_c)(args);
+} fn;
+
+static const char *fn_names =
+ "#libname\0"
+ "funcname_a\0"
+ "funcname_b\0"
+ "@libname2\0"
+ "funcname_c\0"
+ ;
+
+See the nativez-gen header for the options.
+
LICENSE
-------
This is supplied under the permissive 3-clause BSD license. It allows
for commercial use. See also notzed.nativez/legal/LICENSE.
+java.make is covered by the GNU GPL Version 3 or later but is only
+required at build time.
+
Copyright (C) 2018,2019 Michael Zucchi
Redistribution and use in source and binary forms, with or without
#!/usr/bin/perl
# usage [ options ]* def-file.def
-# -b basedir Base directory for any 'header' sections.
-# -I incdir Extra include directory
-# -Iincdir Extra include directory
+
+# -b basedir Base directory for any 'header' sections. It is added to the include path.
# --func-name Function table variable name. Default is `fn'.
# --java-name Java table variable name. Default is 'java'.
# -J Create #defines to map java names to the variable name.
# --java-long Create long java names for object types. Sort of like mangled jni names.
+# All other options and arguments are passed to cproto.
+
$args = "$0 ".join " ", @ARGV;
$java_name = "java";
$func_name = "fn";
$doJ = 0;
$doLong = 0;
+$cproto = "";
-while ($#ARGV >= 0) {
+while ($#ARGV > 0) {
my $cmd = shift;
if ($cmd eq "-b") {
$basedir = shift;
- $includes.=" '-I${basedir}'";
- } elsif ($cmd eq "-I") {
- my $dir = shift;
- $includes.= " '-I$dir'";
- } elsif ($cmd =~ m/^-I/) {
- $includes.= " '$cmd'";
+ $cproto .= " -I '${basedir}'";
} elsif ($cmd eq "--func-name") {
$func_name = shift;
} elsif ($cmd eq "--java-name") {
} elsif ($cmd eq "--java-long") {
$doLong = 1;
} else {
- $def = $cmd;
+ $cproto .= " '$cmd'";
}
}
+$def = shift;
-#die ("`$def': input file doesn't exist") if ! -f $def;
-#die ("`$basedir': doesn't exist") if ! -d $basedir;
+die ("`$def': input file doesn't exist") if ! -f $def;
$header = "";
$librart = "";
-f "$basedir/$header" || die ("header $header not found");
%proto = ();
- open PROTO, "cproto -q -x ${includes} $basedir/$header|";
+ open PROTO, "cproto -q -x ${cproto} $basedir/$header|";
while (<PROTO>) {
chop;