ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From <>
Subject AW: Writing new task: javani
Date Wed, 28 Apr 2010 06:28:37 GMT lists a lot of tasks including preprocessors and jni utilities.


>-----Urspr√ľngliche Nachricht-----
>Von: Mark Bednarczyk [] 
>Gesendet: Dienstag, 27. April 2010 18:04
>Betreff: Writing new task: javani
>I'm writing a new task "javani" and want to see if there was 
>any duplicate
>effort with what I'm proposing.
>The task named 'javani' is a java preprocessor for generating wrapper
>functions in C. Its input is a compiled java classfile, and its output
>either a C or header file to be compiled, or both. The task 
>expands on what
>existing 'javah' task performs by generating C wrapper functions which
>automate some common tasks usually performed manually using JNI C
>programming interface.
>The task can generate source C code (both C and header files), 
>which needs
>to be further compiled by a C compiler. The task can be instructed to
>generate 2 types of output:
>1) A header file, which provides C declarations for functions 
>and JNI to
>java mappings
>2) A C source file containing wrapper functions which can be 
>used to call on
>any java method from C. The code generator takes care of 
>JNI method and field IDs.
>Typically stub and wrapper C functions do not mix and are thus 
>output to
>different C files. Stub files only need to be generated once, 
>while wrapper
>functions can be regenerated every time ant build compiles the code.
>Easily create wrapper functions for any java class (including 
>standard JRE
>classes). This saves the time of trying to manually lookup and 
>cache JNI
>field and method IDs.  You call on C functions only supplying 
>the JNIEnv and
>jobject or jclass parameters and any other parameters declared 
>in the java
>method signature.
>Here is an example java class:
>package org.jnetsoft.jni.stub;
>public class MyClass {
>  public void method1() { }
>  public int method2(char c, byte b, short s, int i, long l, 
>String str)
>{return 0;}
>  private int field1;
>And wrapper functions generated:
>#include <jni.h>
>#include "org_jnetsoft_jni_stub_MyClass.h"
> * Class:     org.jnetsoft.jni.stub.MyClass
> * Method:    onClassLoad
> * Signature: ()V
> */
>JNIEXPORT void JNICALL Java_org_jnetsoft_jni_stub_MyClass_onClassLoad
>  (JNIEnv *env, jclass clazz) {
>	org_jnetsoft_jni_stub_MyClass_class_t *c =
>	memset(c, sizeof(org_jnetsoft_jni_stub_MyClass_class_t), 0);
>	c->clazz = (*env)->NewGlobalRef(env, clazz);
>	c->method1	= (*env)->GetMethodID(env, clazz, 
>"method1", "()V");
>	c->method2	= (*env)->GetMethodID(env, clazz, "method2",
>	c->field1	= (*env)->GetFieldID(env, clazz, "field1", "I");
> * Class:     org.jnetsoft.jni.stub.MyClass
> * Method:    onClassUnload
> * Signature: ()V
> */
>JNIEXPORT void JNICALL Java_org_jnetsoft_jni_stub_MyClass_onClassUnload
>  (JNIEnv *env, jclass clazz) {
>	org_jnetsoft_jni_stub_MyClass_class_t *c =
>	(*env)->DeleteGlobalRef(env, c->clazz);
> * Class:     org.jnetsoft.jni.stub.MyClass
> * Method:    method1
> * Types:     ()
> * Signature: ()V
> */
>void org_jnetsoft_jni_stub_MyClass_method1
>  (JNIEnv *env, jobject obj) {
>	(*env)->CallVoidMethod(env, obj,
> * Class:     org.jnetsoft.jni.stub.MyClass
> * Method:    method2
> * Types:     (char, byte, short, int, long, String, )
> * Signature: (CBSIJLjava/lang/String;)I
> */
>jint org_jnetsoft_jni_stub_MyClass_method2
>  (JNIEnv *env, jobject obj, jchar arg1, jbyte arg2, jshort 
>arg3, jint arg4,
>jlong arg6, jobject arg7) {
>	return (*env)->CallIntMethod(env, obj,
>org_jnetsoft_jni_stub_MyClass_class.method2, arg1, arg2, arg3, 
>arg4, arg6,
>And so forth. The code generator is working already (as seen above), I
>started putting it into an ANT task and figured this would be 
>a good time to
>check the community.
>The generator has no external dependencies and is pure java. 
>The current
>code generator can also generate C "stub" functions for all declared
>'native' methods in java class, but that functionality would 
>be ommitted
>from the task. The long 'namespace' prefix for every function can be
>overwritten with any user specified one. For example in the 
>above sample,
>the namespace prefix used 'org_jnetsoft_jni_stub' could be replaced by
>'javani' task to user supplied one such as 'stub' thus greatly 
>the function and ID names making them more convenient to 
>utilize in user's
>Here is a typical scenario I would envision for usage with this task. A
>programmer would choose which java calls need to be made on 
>java classes
>from native C or C++ code. He would add a list of those 
>classes to his ANT
>build script, through a refid or some other list of classes 
>(typically an
>external .properties file). The build process would proceed in 
>roughly the
>following order:
>1) compile user java code to classfiles
>2) invoke javah to generate stub header files for all native 
>java functions
>(as normally done)
>3) invoke javani to generate wrapper functions and header files for all
>classes and java methods which are expected to be invoked from 
>user's native
>code. User would declare those classes in a list.
>4) compile with a C compiler all the newly generated wrapper 
>functions and
>output to a build area.
>5) compile normal user native (C/C++) code. The code at this stage can
>reference and rely on any wrapper functions and generated header files.
>I use this process in practice with my projects and it works 
>rather well.
>Steps #3 and #4 can easily be incorporated into any build process and
>greatly simplify java method calls from native user space.
>Also note that the wrapper functions can be omitted completely (with an
>option to 'javani' task), and the user can rely on entirely on 
>the cached
>JNI method and field IDs and invoke JNI API directly using 
>those IDs. The
>IDs are exported globally (declared in header files). Once 
>initialized, the
>wrapper functions are simply a convenience. The method and 
>field IDs can be
>utilized directly by the user if preferred over additional overhead of
>wrapper functions.
>There are some limitations. Unlike 'javah' task, my code does 
>not parse the
>binary classfile looking for constants. The task uses java 
>reflection to
>inspect classes, methods and fields. Therefore any constants 
>(static final
>fields) are typically optimized away by the compiler. These constants
>however do exist in the 'javah' generated stub header files, 
>which can be
>incorporated into a build process. The 2 tasks are 
>complimentatory to each
>other. This is one area, where possibly classfile parser used 
>by 'javah'
>could be reused, but I haven't looked into this possibility yet.
>"A government big enough to give you everything you want, is 
>strong enough
>to take everything you have."
>- Thomas Jefferson
>To unsubscribe, e-mail:
>For additional commands, e-mail:

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message