ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mark Bednarczyk" <voyte...@yahoo.com>
Subject RE: Writing new task: javani
Date Wed, 28 Apr 2010 08:49:16 GMT
Hi Jan,
	thanks for pointing that out.

I couldnít find any ANT tasks that generate C wrapper functions, have no
additional runtime requirements and allow custom JNI to java peering/binding
implementation.

There is one project JNI++ which I have looked at before. Itís targeted
toward C++ environments and has a runtime dependency on JNI++ runtime
library. Itís a powerful full-feature library, but overkill for my project
needs.

My project utilizes a custom JNI to java peering/binding for performance
reasons. JNI++ kind of forces you into its own implementation of it. You can
work around it but it defeats the purpose of using something as
comprehensive as JNI++.

I am looking for a simple C based JNI/java preprocessor, classfile wrapper
generator. The task 'javani', modeled after existing 'javah' task, fits in
about 20Kb jar file and has no dependencies (at build or runtime). It
generates straight forward C function wrappers and has tiny amount of static
memory overhead per classfile when a classfile is first loaded by a
ClassLoader. The java/JNI binding/peering implementation, which is where
most of the complexity is typically found, ateast for a library developer
like myself, is left up to the user.

I'd love to be able to use an existing ANT task for this and have someone
else maintain the code. However I am willing to implement 'javani' if I
can't find a suitable alternative and ANT project wants my code.

May be from ANT's perspective, the proper course would be to enhance 'javah'
task. Its currently a wrapper around java SDK tool 'javah'. Itís a task that
setup the environment for the external tool to be called. Works very well
and I use it heavily.  We could however enhance it with a code generator to
generate newer JNI 1.4 level stubs (which javah executable does not
support), but also generate wrapper functions for classfiles? At minimum, it
would certainly make sense for 'javani' to match the 'javah' parameter names
and behavior as much as possible.

Cheers,
mark...

> -----Original Message-----
> From: Jan.Materne@rzf.fin-nrw.de [mailto:Jan.Materne@rzf.fin-nrw.de]
> Sent: Wednesday, April 28, 2010 2:29 AM
> To: dev@ant.apache.org; voytechs@yahoo.com
> Subject: AW: Writing new task: javani
>
> http://ant.apache.org/external.html lists a lot of tasks
> including preprocessors and jni utilities.
>
> Jan
>
> >-----UrsprŁngliche Nachricht-----
> >Von: Mark Bednarczyk [mailto:voytechs@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-unsubscribe@ant.apache.org For
> additional
> >commands, e-mail: dev-help@ant.apache.org
> >
> >



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Mime
View raw message