opensource hardware in nz

Tuesday, May 27, 2008

Came across this site that stocks some really fun looking hardware. Of particular note is stocking only opensource-capable routers, laptops without an OS (no M$ tax!) and single-board computers that use only 5-7 watts that you could really have some fun with. Oh and who could pass up a GSM modem with built-in GPS? Oh, the gadgetry and geekyness.

nicegear.co.nz

jni - call C/C++/Assembly from Java

Friday, May 23, 2008

  1. Create Java class containing native method(s) (static or instance) defining interface with C code.
    public class Processor {
    public static native double process(double x, double y);
    }

  2. Compile to Java class file.

  3. Run
    javah -jni [-o path/to/CProcessor.h] Processor
    to generate C header file from the Java. Eg. CProcessor.h:
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Processor */

    #ifndef _Included_Processor
    #define _Included_Processor
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
    * Class: Processor
    * Method: process
    * Signature: (DD)D
    */
    JNIEXPORT jdouble JNICALL Java_Processor_process
    (JNIEnv *, jclass, jdouble, jdouble);

    #ifdef __cplusplus
    }
    #endif
    #endif

  4. Create a .c C source file - this is the stub to call the target code. Include header and "Processor.h". The angle brackets mean it is registered as a library file for the compiler, whereas the speech marks denote a stand-alone header file. May need to include the path the Processor.h within the speech marks. Here is a simple example that just sums the two input numbers, rather than calling any other C:
    #include <jni.h>
    #include <math.h>
    #include "../headers/CProcessor.h"
    #include <stdio.h>
    JNIEXPORT jdouble JNICALL Java_Processor_process
    (JNIEnv *env , jclass obj, jdouble val1, jdouble val2) {
    return (val1+val2);
    }

  5. Run (eg for linux)
    gcc -shared -I /usr/lib/jvm/java-1.5.0-sun-1.5.0.15/include/ -I
    /usr/lib/jvm/java-1.5.0-sun-1.5.0.15/include/linux/ -o CProcessor.so CProcessor.c
    to create the library file (indicated by 'shared' flag). Any compiler errors about missing .h headers should be solved by the inclusion (-I) of the jni and jni for linux paths.

  6. Either in a method inside original Java class, or in a new calling class, create a static block to either load (System.load()) the .so library via its file path, or load (System.loadLibrary()) a registered library (e.g. dll on Windows) via system-specific addressing.

  7. Once the static block has loaded the library, the methods are available either statically or from an object as determined in 1.
    public class Caller {
    static {
    System.load("/home/me/_projects/JNI/C/CProcessor.so");
    }
    public static void main(String[] args) {
    double result = Processor.process(2, 3);
    System.out.println(result);
    }
    }
    In this case our Processor in Java calls the CProcessor in C which adds the 2 doubles we passed it and returns a double. Here it is 2 + 3 with the output 5.