# HG changeset patch # User cslag # Date 1460243914 18000 # Node ID 4ee8d6aa772102a113db79d1c113507eba5cdae6 # Parent 40a2c41980160925ed0c1fbcf964ba5db66271c5 - java binding cleanup, exposed free functions (not very oo, this entire binding) - java binding examples diff -r 40a2c4198016 -r 4ee8d6aa7721 java/jdc/Makefile --- a/java/jdc/Makefile Wed Mar 30 23:40:52 2016 +0200 +++ b/java/jdc/Makefile Sat Apr 09 18:18:34 2016 -0500 @@ -15,7 +15,7 @@ org_dyncall_DC.h: org/dyncall/DC.class javah -jni org.dyncall.DC -org/dyncall/DC.class: +org/dyncall/DC.class: org/dyncall/DC.java cd org/dyncall/ && javac DC.java .PHONY: build clean diff -r 40a2c4198016 -r 4ee8d6aa7721 java/jdc/examples/UnixLibCExample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/jdc/examples/UnixLibCExample.java Sat Apr 09 18:18:34 2016 -0500 @@ -0,0 +1,66 @@ +import org.dyncall.DC; + +// This example tries to make use of each call in the binding. +class UnixLibCExample +{ + public static void main(String args[]) + { + long lib = DC.loadLibrary("/usr/lib/libc.so"); + System.out.format("libc.so handle: %x\n", lib); + + long f0 = DC.find(lib, "strlen"); + System.out.format("found strlen at: %x\n", f0); + + long f1 = DC.find(lib, "strstr"); + System.out.format("found strstr at: %x\n", f1); + + long f2 = DC.find(lib, "strncmp"); + System.out.format("found strncmp at: %x\n", f2); + + long vm = DC.newCallVM(4096); + DC.reset(vm); + System.out.format("dcGetError() = %d\n", DC.getError(vm)); + DC.mode(vm, 1234567); // bogus mode, should set error + System.out.format("dcGetError() = %d (after trying to set bogus mode)\n", DC.getError(vm)); + DC.mode(vm, DC.C_DEFAULT); // good mode, should clear error + System.out.format("dcGetError() = %d (after setting valid mode)\n", DC.getError(vm)); + + // String param. + DC.argString(vm, "This is a Java string of 33 chars"); + int r0 = DC.callInt(vm, f0); + System.out.format("strlen(\"This is a Java string of 33 chars\") = %d\n", r0); + + // String param and string/pointer return. + DC.reset(vm); + DC.argString(vm, "This is a Java string"); + DC.argString(vm, "Java"); + String r1 = DC.callString(vm, f1); // will return a copy of the output string, not like a pointer in C + System.out.format("strlen(\"This is a Java string\", \"Java\") = %s\n", r1); + long r1l = DC.callPointer(vm, f1); // test returning the pointer as long + System.out.format("strlen(\"This is a Java string\", \"Java\") = 0x%x (returned pointer, pointless here, but serves as example)\n", r1l); + + DC.reset(vm); + DC.argString(vm, "This is a Java string"); + DC.argString(vm, "This is"); + DC.argInt(vm, 6); + int r2 = DC.callInt(vm, f2); + System.out.format("strlen(\"This is a Java string\", \"This is\", 6) = %d\n", r2); + DC.reset(vm); + DC.argString(vm, "This is a Java string"); + DC.argString(vm, "This is"); + DC.argInt(vm, 8); + r2 = DC.callInt(vm, f2); + System.out.format("strlen(\"This is a Java string\", \"This is\", 8) = %d\n", r2); + + //DC.reset(vm); + //DC.argDouble(vm, 2.); + //DC.argDouble(vm, 10.); + //double r1 = DC.callDouble(vm, f1); + //System.out.format("pow(2., 10.) = %f\n", r1); + + // Done, cleanup. + DC.freeCallVM(vm); + DC.freeLibrary(lib); + } +} + diff -r 40a2c4198016 -r 4ee8d6aa7721 java/jdc/examples/UnixMathExample.java --- a/java/jdc/examples/UnixMathExample.java Wed Mar 30 23:40:52 2016 +0200 +++ b/java/jdc/examples/UnixMathExample.java Sat Apr 09 18:18:34 2016 -0500 @@ -4,11 +4,11 @@ { public static void main(String args[]) { - long lib = DC.load("/usr/lib/libm.so"); + long lib = DC.loadLibrary("/usr/lib/libm.so"); System.out.format("libm.so handle: %x\n", lib); long f0 = DC.find(lib, "sqrtf"); - System.out.format("found sqrft at: %x\n", f0); + System.out.format("found sqrtf at: %x\n", f0); long f1 = DC.find(lib, "pow"); System.out.format("found pow at: %x\n", f1); @@ -23,6 +23,10 @@ DC.argDouble(vm, 10.); double r1 = DC.callDouble(vm, f1); System.out.format("pow(2., 10.) = %f\n", r1); + + // Done, cleanup. + DC.freeCallVM(vm); + DC.freeLibrary(lib); } } diff -r 40a2c4198016 -r 4ee8d6aa7721 java/jdc/org/dyncall/DC.java --- a/java/jdc/org/dyncall/DC.java Wed Mar 30 23:40:52 2016 +0200 +++ b/java/jdc/org/dyncall/DC.java Sat Apr 09 18:18:34 2016 -0500 @@ -51,9 +51,11 @@ ; public static native long newCallVM(int size); + public static native void freeCallVM(long vmhandle); - public static native long load(String libname); - public static native long find(long libhandle, String symbol); + public static native long loadLibrary(String libname); + public static native void freeLibrary(long libhandle); + public static native long find(long libhandle, String symbol); //public static native int symsCount(long libhandle); //public static native String symsName (long libhandle, int index); diff -r 40a2c4198016 -r 4ee8d6aa7721 java/jdc/org_dyncall_DC.c --- a/java/jdc/org_dyncall_DC.c Wed Mar 30 23:40:52 2016 +0200 +++ b/java/jdc/org_dyncall_DC.c Sat Apr 09 18:18:34 2016 -0500 @@ -1,25 +1,51 @@ +#include #include "org_dyncall_DC.h" #include "dyncall.h" #include "dynload.h" +// Bookkeping to clean up on reset. +static int gc_snum = 0; +static jobject* gc_jstr = NULL; +static const char** gc_cstr = NULL; +static void cleanupHeldStrings(JNIEnv *pEnv) +{ + for(int i=0; iReleaseStringUTFChars(pEnv, gc_jstr[i], gc_cstr[i]); + + free(gc_jstr); gc_jstr = NULL; + free(gc_cstr); gc_cstr = NULL; + gc_snum = 0; + +} + + jlong JNICALL Java_org_dyncall_DC_newCallVM(JNIEnv *pEnv, jclass clazz, jint size) { return (jlong)dcNewCallVM(size); -//@@@ free } -jlong JNICALL Java_org_dyncall_DC_load(JNIEnv *pEnv, jclass clazz, jstring s) +void JNICALL Java_org_dyncall_DC_freeCallVM(JNIEnv *pEnv, jclass clazz, jlong vm) +{ + cleanupHeldStrings(pEnv); + dcFree((DCCallVM*)vm); +} + +jlong JNICALL Java_org_dyncall_DC_loadLibrary(JNIEnv *pEnv, jclass clazz, jstring s) { jlong l = 0; const char *sz = (*pEnv)->GetStringUTFChars(pEnv, s, NULL); if(sz != NULL) { l = (jlong)dlLoadLibrary(sz); (*pEnv)->ReleaseStringUTFChars(pEnv, s, sz); -//@@@ free } return l; } +void JNICALL Java_org_dyncall_DC_freeLibrary(JNIEnv *pEnv, jclass clazz, jlong libhandle) +{ + dlFreeLibrary((DLLib*)libhandle); +} + jlong JNICALL Java_org_dyncall_DC_find(JNIEnv *pEnv, jclass clazz, jlong libhandle, jstring s) { jlong l = 0; @@ -43,13 +69,13 @@ void JNICALL Java_org_dyncall_DC_mode(JNIEnv *pEnv, jclass clazz, jlong vm, jint i) { - dcMode((DCCallVM*)vm, i);//@@@test + dcMode((DCCallVM*)vm, i); } void JNICALL Java_org_dyncall_DC_reset(JNIEnv *pEnv, jclass clazz, jlong vm) { + cleanupHeldStrings(pEnv); dcReset((DCCallVM*)vm); -//@@@add cleanup code here for temporary memory held by jni } void JNICALL Java_org_dyncall_DC_argBool(JNIEnv *pEnv, jclass clazz, jlong vm, jboolean b) @@ -69,7 +95,7 @@ void JNICALL Java_org_dyncall_DC_argInt(JNIEnv *pEnv, jclass clazz, jlong vm, jint i) { - dcArgInt((DCCallVM*)vm, i);//@@@test + dcArgInt((DCCallVM*)vm, i); } void JNICALL Java_org_dyncall_DC_argLong(JNIEnv *pEnv, jclass clazz, jlong vm, jlong l) @@ -107,8 +133,13 @@ const char *sz = (*pEnv)->GetStringUTFChars(pEnv, s, NULL); if(sz != NULL) { dcArgPointer((DCCallVM*)vm, (DCpointer)sz); - //(*pEnv)->ReleaseStringUTFChars(pEnv, s, sz); - //@@@ free this string when vm is destroyed, reset + + // Bookkeeping, to later release on reset or destruction of vm. + gc_jstr = realloc(gc_jstr, (gc_snum+1)*sizeof(jobject)); + gc_cstr = realloc(gc_cstr, (gc_snum+1)*sizeof(const char*)); + gc_jstr[gc_snum] = s; + gc_cstr[gc_snum] = sz; + ++gc_snum; } } @@ -134,7 +165,7 @@ jint JNICALL Java_org_dyncall_DC_callInt(JNIEnv *pEnv, jclass clazz, jlong vm, jlong target) { - return dcCallInt((DCCallVM*)vm, (DCpointer)target);//@@@test + return dcCallInt((DCCallVM*)vm, (DCpointer)target); } jlong JNICALL Java_org_dyncall_DC_callLong(JNIEnv *pEnv, jclass clazz, jlong vm, jlong target) @@ -159,16 +190,16 @@ jlong JNICALL Java_org_dyncall_DC_callPointer(JNIEnv *pEnv, jclass clazz, jlong vm, jlong target) { - return (jlong)dcCallPointer((DCCallVM*)vm, (DCpointer)target);//@@@test + return (jlong)dcCallPointer((DCCallVM*)vm, (DCpointer)target); } jstring JNICALL Java_org_dyncall_DC_callString(JNIEnv *pEnv, jclass clazz, jlong vm, jlong target) { - return (*pEnv)->NewStringUTF(pEnv, dcCallPointer((DCCallVM*)vm, (DCpointer)target));//@@@test + return (*pEnv)->NewStringUTF(pEnv, dcCallPointer((DCCallVM*)vm, (DCpointer)target)); } jint JNICALL Java_org_dyncall_DC_getError(JNIEnv *pEnv, jclass clazz, jlong vm) { - return dcGetError((DCCallVM*)vm);//@@@test + return dcGetError((DCCallVM*)vm); }