http://ant.apache.org/external.html lists a lot of tasks including preprocessors and jni utilities.
Jan >-----Ursprüngliche Nachricht----- >Von: Mark Bednarczyk [mailto:voyte...@yahoo.com] >Gesendet: Dienstag, 27. April 2010 18:04 >An: dev@ant.apache.org >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. > >Summary: >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 >maintaining/caching >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" > >org_jnetsoft_jni_stub_MyClass_class_t >org_jnetsoft_jni_stub_MyClass_class; > >/* > * 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 = >&org_jnetsoft_jni_stub_MyClass_class; > > 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", >"(CBSIJLjava/lang/String;)I"); > > 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 = >&org_jnetsoft_jni_stub_MyClass_class; > > (*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, >org_jnetsoft_jni_stub_MyClass_class.method1); >} > >/* > * 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, >arg7); >} >[truncated...] >--------------------------------------------------------------- >----------- > >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 >shortening >the function and ID names making them more convenient to >utilize in user's >code. > >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. > >Cheers, >mark... > >"A government big enough to give you everything you want, is >strong enough >to take everything you have." > >- Thomas Jefferson > > > >--------------------------------------------------------------------- >To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org >For additional commands, e-mail: dev-h...@ant.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org For additional commands, e-mail: dev-h...@ant.apache.org