- cat jnicc
filename=$(basename $1)
base=${filename%.*}
ext=${filename##*.}
gcc -shared -I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/linux $filename -o lib$base.so
#gcc -I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/linux $filename -o $base -L/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/i386/ -ljava -lverify -L/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/i386/client/ -ljvm
- Environment
export LD_LIBRARY_PATH=.
- HelloWord
class HelloWorld {
private native void print();
public static void main(String[] args) {
new HelloWorld().print();
}
static {
System.loadLibrary("HelloWorld");
}
}
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
//"env" point to a JNI functions list, includes a lot of JNI methods;
// "obj" is similiar to "this" pointer in C++;
printf("Hello World!\n");
return;
}
$ javac HelloWorld.java
$ javah -jni HelloWorld ; Generated HelloWorld.h
#$ cc -shared -I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/linux HelloWorld.c -o libHelloWorld.so
$ ./jnicc HelloWorld
$ java HelloWorld
Hello World!
- Accessing Arrays Of Objects
JNIEXPORT jobjectArray JNICALL
class ObjectArrayTest {
private static native int[][] initInt2DArray(int size);
public static void main(String[] args) {
int[][] i2arr = initInt2DArray(3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(" " + i2arr[i][j]);
}
System.out.println();
}
}
static {
System.loadLibrary("ObjectArrayTest");
}
}
Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclass cls, jint size) //For object accessing uses the jclass and not jobject ?
{
jobjectArray result;
int i;
jclass intArrCls = (*env)->FindClass(env, "[I"); // "[I" equals int[] ;
if (intArrCls == NULL) {
return NULL; /* exception thrown */
}
result = (*env)->NewObjectArray(env, size, intArrCls, NULL);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
for (i = 0; i < size; i++) {
jint tmp[256]; /* make sure it is large enough! */
int j;
jintArray iarr = (*env)->NewIntArray(env, size);
if (iarr == NULL) {
return NULL; /* out of memory error thrown */
}
for (j = 0; j < size; j++) {
tmp[j] = i + j;
}
(*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);
(*env)->SetObjectArrayElement(env, result, i, iarr); // copyiarr to i2arr[i] ;
(*env)->DeleteLocalRef(env, iarr);
}
return result;
}
- Accessing Fields and Methods
class InstanceMethodCall {
private native void nativeMethod();
private void callback() {
System.out.println("In Java");
}
public static void main(String args[]) {
InstanceMethodCall c = new InstanceMethodCall();
c.nativeMethod();
}
static {
System.loadLibrary("InstanceMethodCall");
}
}
JNIEXPORT void JNICALL
Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid =
(*env)->GetMethodID(env, cls, "callback", "()V");
// (): parameter; V: return type
//"(I)I" : int xxxx(int x); "(Ljava/lang/String;)Ljava/lang/String;": String xxxx(String xxx); "([Ljava/lang/String;)V" : void xxxx(String args[])
if (mid == NULL) {
return; /* method not found */
}
printf("In C\n");
(*env)->CallVoidMethod(env, obj, mid);
}
- C calling JAVA code
ENV: export LD_LIBRARY_PATH=./:/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/i386:/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/i386/client
public class Sample2
{
public static int intMethod(int n) { return n*n; }
public static boolean booleanMethod(boolean bool) { return !bool; }
}
#include <jni.h>
#include <memory.h>
#ifdef _WIN32
#define PATH_SEPARATOR ';'
#else
#define PATH_SEPARATOR ':'
#endif
long square(int num);
int main()
{
JavaVMOption options[1];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
jint square;
jboolean not;
options[0].optionString = "-Djava.class.path=.";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;
status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (status != JNI_ERR)
{
cls = (*env)->FindClass(env, "Sample2");
if(cls !=0)
{ mid = (*env)->GetStaticMethodID(env, cls, "intMethod", "(I)I");
if(mid !=0)
{ square = (*env)->CallStaticIntMethod(env, cls, mid, 5);
printf("Result of intMethod: %d\n", square);
}
mid = (*env)->GetStaticMethodID(env, cls, "booleanMethod", "(Z)Z");
if(mid !=0)
{ not = (*env)->CallStaticBooleanMethod(env, cls, mid, 1);
printf("Result of booleanMethod: %d\n", not);
}
}
(*jvm)->DestroyJavaVM(jvm);
return 0;
}
else
return -1;
}
long square(int num) { return (long) num*num; }
$ javac Sample2.java
$ gcc -I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/linux Sample2.c -o Sample2 -L/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/i386/ -ljava -lverify -L/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/i386/client/ -ljvm
- One on One Mapping
class C {
public static native int atol(String str);
}
class Win32 {
public static native int CreateFile(
String fileName, // file name
int desiredAccess, // access (read-write) mode
int shareMode, // share mode
int[] secAttrs, // security attributes
int creationDistribution, // how to create
int flagsAndAttributes, // file attributes
int templateFile); // file with attr. to copy
}
class OneToOne {
public static void main(String[] args) {
System.out.println("atol(\"123\") = " + C.atol("123"));
System.out.println("Creating a file called TestFile.tst in the current directory...");
Win32.CreateFile("TestFile.tst",
0x40000000, // GENERIC_WRITE
0, // not sharable
null, // no security
2, // CREATE_ALWAYS
0x00000080, // FILE_ATTRIBUTE_NORMAL
0); // no template file
}
static {
System.loadLibrary("OneToOne");
}
}
#include <windows.h>
#include <jni.h>
#include <stdio.h>
#include "C.h"
#include "Win32.h"
JNIEXPORT jint JNICALL
Java_C_atol(JNIEnv *env, jclass cls, jstring str)
{
const char *cstr = env->GetStringUTFChars(str, 0);
if (cstr == NULL) {
return 0; /* out of memory */
}
int result = atol(cstr);
env->ReleaseStringUTFChars(str, cstr);
return result;
}
JNIEXPORT jint JNICALL Java_Win32_CreateFile(
JNIEnv *env,
jclass cls,
jstring fileName, // file name
jint desiredAccess, // access (read-write) mode
jint shareMode, // share mode
jintArray secAttrs, // security attributes
jint creationDistribution, // how to create
jint flagsAndAttributes, // file attributes
jint templateFile) // file with attr. to copy
{
jint result = 0;
jint *cSecAttrs = NULL;
if (secAttrs) {
cSecAttrs = env->GetIntArrayElements(secAttrs, 0);
if (cSecAttrs == NULL) {
return 0; /* out of memory */
}
}
const char *cFileName = env->GetStringUTFChars(fileName, NULL);
if (cFileName) {
/* call the real Win32 function */
result = (jint)CreateFile(cFileName,
desiredAccess,
shareMode,
(SECURITY_ATTRIBUTES *)cSecAttrs,
creationDistribution,
flagsAndAttributes,
(HANDLE)templateFile);
//free(cFileName);
}
/* else fall through, out of memory exception thrown */
if (secAttrs) {
env->ReleaseIntArrayElements(secAttrs, cSecAttrs, 0);
}
return result;
}
$ javac OneToOne.java
$ javah -jni C
$ javah -jni W32
$ jnicpp OneToOne
$ java OneToOne
atol("123") = 0
Creating a file called TestFile.tst in the current directory...