Tried anybody do like here: Java programming with JNI
But compiled a dll from Nim? Does exist an example?
Thanks, but I think jnim using as run Java programm on JVM from Nim
but I need run C code (wrote on Nim and compled to dll) from Java.
You can get the source code here. There are 5 files.
how to build sample code:
javac Sample1.java
javah -classpath . Sample1
nim c --app:lib --passL:"-static-libgcc" --passL:"-Wl,--kill-at" Sample1
You can omit -static-libgcc part, but you must use "-Wl,--kill-at" to remove '@' from exported symbol name.
don't forget to include jni_export in all your project files that uses jni.nim(don't import it, use include)
and finally, run the java vm:
java Sample1
EDIT: beware: if there exist more than one dll plugin written in Nim, please use compiler switch "-d:useNimRtl", (I never tested it before, but the documentation says like that)
EDIT: The Sample code provided are written in C style. if you want to try C++ style, please read Playing with CPP VTABLE from Nim
avoid using proc with va_list too, Nim don't have proper support for this C feature(I don't have time to explore/experiment with va_list in Nim yet)
tested with:
javac 1.7.0_79
java version "1.7.0_79" Java(TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
gcc version 5.3.0 (GCC) Target: x86_64-w64-mingw32 Thread model: win32
Nim Compiler Version 0.14.3 (2016-06-15) [Windows: amd64]
Thanks all!
@jangko, I tried your code. It works.
But it exist one issue if I manipulate with 'cap' variable in proc Java_Sample1_stringMethod: for example cap.add("test")
and in JAVA for(int i=0; i<1000; i++){ text = sample.stringMethod("JAVA"+i); }
then I get:
Because nim's GC does it.
I found a solution: in the Sample1.nim at start
GC_disable()
and later somewhere run proc with:
GC_enable()
GC_fullCollect()
GC_disable()
or does exist better solution?
What have I changed: in Sample1.java main function now is:
public static void main(String[] args) {
System.loadLibrary("Sample1");
Sample1 sample = new Sample1();
int square = sample.intMethod(5);
boolean bool = sample.booleanMethod(true);
String text = "";
for(int i=0; i<1000; i++){
text = sample.stringMethod("JAVA"+i);
}
int sum = sample.intArrayMethod(new int[]{1,1,2,3,5,8,13} );
System.out.println("intMethod: " + square);
System.out.println("booleanMethod: " + bool);
System.out.println("stringMethod: " + text);
System.out.println("intArrayMethod: " + sum);
}
in Sample1.nim proc Java_Sample1_stringMethod now is:
proc Java_Sample1_stringMethod(env: ptr JNIEnv, obj: jobject, input: jstring): jstring {.JNIEXPORT.} =
var isCopy: jboolean
var str = env[].GetStringUTFChars(env, input, isCopy)
var cap = $str
cap.add("test")
env[].ReleaseStringUTFChars(env, input, str)
result = env[].NewStringUTF(env, cap)
Then I get EXCEPTION_ACCESS_VIOLATION (0xc0000005)
tested with:
javac 1.8.0_20
java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b18) Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 5.3.0
Nim Compiler Version 0.14.3 (2016-07-13) [Windows: amd64]
Thanks...
Now I can reproduce the error too. Very interesting, this code below works, maybe someone else can explain this phenomenon
cap.add("test")
var tmp = cap
env[].ReleaseStringUTFChars(env, input, str)
result = env[].NewStringUTF(env, tmp)