Hi All,
I am writing a plugin for ImageJ with native code, i.e it used JNI I first created a simple 'C' program "H_.c" for printing "Hello World!". #include <windows.h> #include <winuser.h> #include <jni.h> #include "H_.h" #include <stdlib.h> #include <stdio.h> JNIEXPORT void JNICALL Java_H__sayHello (JNIEnv *env, jobject obj) { printf("I am here!\n"); return; } Then I wrote a java program "H_.java" for calling this C program(I did this by using the system.loadlibrary(dll_name) command). #include <windows.h> #include <winuser.h> #include <jni.h> #include "H_.h" #include <stdlib.h> #include <stdio.h> JNIEXPORT void JNICALL Java_H__sayHello (JNIEnv *env, jobject obj) { printf("I am here!\n"); return; } H_.h is the header file I generated through eclipse. I then used the command:- gcc -I"C:\Program Files\Java\jdk1.6.0_32\include" -I"C:\Program Files\Java jdk1.6.0_32\include\win32" -o H_.o H_.c gcc -shared -o H_.dll H_.o H_.def I placed the generated .dll file in the imageJ folder and H_.java in the imageJ/plugins folder and when I compiled this in the ImageJ I got the error :- java.lang.UnsatisfiedLinkError: H_.sayHello()V > at H_.sayHello(Native Method) > at H_.run(H_.java:18) > at ij.IJ.runUserPlugIn(IJ.java:183) > at ij.ImageJ.runUserPlugIn(ImageJ.java:268) > at ij.plugin.PlugInExecuter.run(Compiler.java:264) > at java.lang.Thread.run(Thread.java:619) It would be of a great help if anyone could help me in solving this. Thanks & Regards, Lakshmi |
Hi Lakshmi,
On Tue, 22 May 2012, lakshmi narjala wrote: > I am writing a plugin for ImageJ with native code, i.e it used JNI > > I first created a simple 'C' program "H_.c" for printing "Hello World!". > > #include <windows.h> > #include <winuser.h> > #include <jni.h> These should not need to be included explicitly in the .c file since they are already included in H_.h. > #include "H_.h" > #include <stdlib.h> > #include <stdio.h> > JNIEXPORT void JNICALL Java_H__sayHello (JNIEnv *env, jobject obj) > { > printf("I am here!\n"); > return; > } No indentation? If you code a lot, you might want to learn hard-won lessons by old-timers: code style really helps maintain high-quality software. Oh, and there is no need for an explicit return at the end of the function. Only if a value needs to be returned, which is not the case here. > Then I wrote a java program "H_.java" for calling this C program(I did this > by using the system.loadlibrary(dll_name) command). > > #include <windows.h> > #include <winuser.h> > #include <jni.h> > #include "H_.h" > #include <stdlib.h> > #include <stdio.h> > JNIEXPORT void JNICALL Java_H__sayHello (JNIEnv *env, jobject obj) > { > printf("I am here!\n"); > return; > } This is not H_.java, but H_.c again, correct? > H_.h is the header file I generated through eclipse. I then used the > command:- > > gcc -I"C:\Program Files\Java\jdk1.6.0_32\include" -I"C:\Program Files\Java > jdk1.6.0_32\include\win32" -o H_.o H_.c > > gcc -shared -o H_.dll H_.o H_.def > > I placed the generated .dll file in the imageJ folder It is bad style to put .dll files into the top-level directory. Just think about the situation when you need to support both 32-bit and 64-bit Windows: the file would then have the same name. > and H_.java in the imageJ/plugins folder and when I compiled this in the > ImageJ I got the error :- > > java.lang.UnsatisfiedLinkError: H_.sayHello()V > > at H_.sayHello(Native Method) > > at H_.run(H_.java:18) > > at ij.IJ.runUserPlugIn(IJ.java:183) > > at ij.ImageJ.runUserPlugIn(ImageJ.java:268) > > at ij.plugin.PlugInExecuter.run(Compiler.java:264) > > at java.lang.Thread.run(Thread.java:619) So you did not only compile it as you said, but also run it. But the problem is that the library was not loaded, hence the UnsatisfiedLinkError. Most likely the call to System.loadLibrary() is not even performed. In general, JNI is pretty tricky. Development is definitely very tedious. For example, should you want to modify the native part, you have to restart Java: a native library cannot be unloaded, and loading it again in the same ClassLoader will fail, loading it in another ClassLoader might succeed but the library still cannot be used. There is also the problem if you need to use a native library that has dependencies which you also need to provide yourself. Then you get into the "fun" land of PATH and java.library.path. In Fiji, we tried very hard to hide all those problems away (although you still cannot unload or reload native libraries, that is a real Java limitation we could not overcome); just store your library in lib/win32/ (or lib/win64/ for 64-bit libraries) and use the convenience methods in fiji-lib.jar's fiji.JNI class. An example can be found in Fiji's source code: https://github.com/fiji/fiji/tree/master/src-plugins/JNI_Example Good luck! Johannes |
In reply to this post by lakshmi
Hi Johannes,
Thank you very much for the reply. I have made the changes you mentioned. I guess the problem is with .java file too.. I have pasted the java file here, could you please let me know if I need to make any changes to it? (Not knowing which to import, I have imported many of them!) import ij.*; import ij.process.*; import ij.gui.*; import java.awt.*; import ij.plugin.*; import ij.plugin.frame.*; import java.lang.String; public class H_ implements PlugIn { static {System.loadLibrary("H");}//H is the dll file native void sayHello(); public void run(String arg) { sayHello(); } } This is the .C file: #include "H_.h" #include <stdlib.h> #include <stdio.h> JNIEXPORT void JNICALL Java_H__sayHello (JNIEnv *env, jobject obj) { printf("I am here!\n"); } I generated the .H from eclipse itself.. For a normal plugin(i.e without ImageJ in picture, I placed the .dll file in C:/Windows/System32 folder, where should the dll file be placed for ImageJ) Is there anything else I need to do? Thanks & Regards, Lakshmi |
Hi Lakshmi,
please make sure to Cc: me (or reply to me and Cc: the list) to guarantee that I do not miss your mail among the 150 mails I get per day. On Wed, 23 May 2012, Lakshmi Narjala wrote: > Thank you very much for the reply. I have made the changes you > mentioned. I guess the problem is with .java file too.. I have pasted > the java file here, could you please let me know if I need to make any > changes to it? (Not knowing which to import, I have imported many of > them!) > > > import ij.*; > import ij.process.*; > import ij.gui.*; > import java.awt.*; > import ij.plugin.*; > import ij.plugin.frame.*; Usually, it is better to have explicit imports. Otherwise class names can be shadowed by random .jar files in the class path. Besides, you only use ij.plugin.PlugIn, so you can reduce that block to a single explicit statement. > import java.lang.String; All classes in java.lang are auto-imported, no need to do that explicitly. > public class H_ implements PlugIn { > > static > {System.loadLibrary("H");}//H is the dll file Loading the library this way requires H.dll to be in a directory listed in the environment variable called PATH as well as in the Java system property java.library.path. There are really three options now: 1) use System.load(path) with the absolute path instead (e.g. C:/imagej/lib/win32/H.dll) 2) start Java appropriately, i.e. adjusting PATH and java.library.path before launching the JVM 3) use Fiji's convenience methods to do essentially the same as 2) but without all that hassle. > For a normal plugin(i.e without ImageJ in picture, I placed the .dll > file in C:/Windows/System32 folder, where should the dll file be placed > for ImageJ) Heh, that is so Windows ;-) In modern Windows installations, regular users cannot write into C:/Windows/system32. The common way is to adjust the PATH variable which Windows uses to determine where to find .exe and .dll files. Ciao, Johannes |
Hi Lakshmi,
On Wed, 23 May 2012, lakshmi narjala wrote: > 1) I din't find the path C:/imagej/lib/win32/H.dll i.e I dint find win32 > in imageJ, where else am I supposed to put. My suggestion was to create that directory, to have distinct places for files that are platform-dependent. > 2) Also, what is meant by 2) start Java appropriately, i.e. adjusting PATH > and java.library.path before launching the JVM May I suggest just to use Fiji? I mean, I could explain exactly what steps Fiji does so that the JVM is started with the proper settings, but that would take some time, and my friends actually wait for me right this moment to hike into the mountains, so I do not have the time right now ;-) Ciao, Johannes |
In reply to this post by lakshmi
Hi,
I placed the dll file in the directory that u said and I think I set that path in the environment variables(though I am not sure if I did the proper thing) I am still getting the same error.. what else needs to be done? Does anybody have the solution for this? |
Hi Lakshmi,
On Thu, May 24, 2012 at 2:15 PM, Lakshmi Narjala <[hidden email]>wrote: > Hi, > > I placed the dll file in the directory that u said and I think I set that > path in the environment variables(though I am not sure if I did the proper > thing) I am still getting the same error.. what else needs to be done? > > Does anybody have the solution for this? > I will second Johannes's suggestion to use Fiji. You do know that Fiji Is Just ImageJ, right? -Curtis _______________________________________________________ ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by lakshmi
Hi Lakshmi,
On Thu, 24 May 2012, Lakshmi Narjala wrote: > I placed the dll file in the directory that u said and I think I set > that path in the environment variables(though I am not sure if I did the > proper thing) I am still getting the same error.. what else needs to be > done? I actually forgot that there was an outstanding issue with the JNI support in Fiji on Windows. Probably the same thing that bit you; I just was able to fix it today (see https://github.com/fiji/fiji/commit/021185ce). I also wrote a very compressed introduction into JNI here: http://fiji.sc/JNI So here is my suggestion to get quickly to some working setup on Windows: Download and install msysgit from http://msysgit.github.com/, clone git://fiji.sc/fiji.git in msysgit and build it with "cd fiji && sh Build.sh". Then call "sh Build.sh plugins/JNI_Example.jar". To test it, run "./ImageJ --console", load the Clown example and run Plugins>JNI>JNI Example. In the console, you should see some statistics that were calculated by the C code. You can follow the JNI Example to implement your own plugin and follow the instructions at http://fiji.sc/Adding_Update_Sites to set up and populate your own update site with the result. Ciao, Johannes _______________________________________________________ ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi Johannes,
I followed the steps. Everything went well except the last step. when I gave the command: sh.Build sh plugins/JNI_Example.jar, It failed with the error :- user1@AGR-2206-SMWK1 /C/Git/fiji (master) $ sh Build.sh plugins/JNI_Example.jar Building plugins/Fiji_Updater.jar <- src-plugins/Fiji_Updater/fiji... Building ImageJ <- plugins/Fiji_Updater.jar Updating the Fiji database (Updating from Fiji site) Updating the Fiji database 0/1 Updating from Fiji site done Done: Updating the Fiji database Czech Summer (ImageJ-win64.exe) ImageJ-win64.exe done Czech Summer 583168/595112 Czech Summer (jars/ij-launcher.jar) jars/ij-launcher.jar done Done: Czech Summer Not updating ImageJ-win64.exe (INSTALLED) Not updating jars/ij-launcher.jar (INSTALLED) Building jars/fiji-lib.jar <- src-plugins/fiji-lib/fiji/tool/ToolW... Note: src-plugins\fiji-lib\fiji\util\gui\JFrameCommandFinder.java uses or overri des a deprecated API. Note: Recompile with -Xlint:deprecation for details. Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. Building plugins/JNI_Example.jar <- src-plugins/JNI_Example/plugin... src-plugins/JNI_Example/JNI_Example.c:1:0: sorry, unimplemented: 64-bit mode not compiled in Failed: 1 in rule plugins/JNI_Example.jar <- src-plugins/JNI_Example/plugin... in rule <- plugins/JNI_Example.jar And then when I tried to run the JNI_Example in Fiji, I got the error: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at ij.Command.runPlugIn(Command.java:146) at ij.Command.runCommand(Command.java:95) at ij.Executer.run(Executer.java:64) at java.lang.Thread.run(Thread.java:662) Caused by: java.lang.UnsatisfiedLinkError: no JNI_Example.dll in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734) at java.lang.Runtime.loadLibrary0(Runtime.java:823) at java.lang.System.loadLibrary(System.java:1028) at fiji.JNI.loadLibrary(JNI.java:80) at fiji.JNI.loadLibrary(JNI.java:71) at JNI_Example.run(JNI_Example.java:23) at ij.plugin.filter.PlugInFilterRunner.processOneImage(PlugInFilterRunner.java:256) at ij.plugin.filter.PlugInFilterRunner.<init>(PlugInFilterRunner.java:105) at ij.IJ.runUserPlugIn(IJ.java:187) at ij.IJ.runPlugIn(IJ.java:152) ... 8 more Can you please advice on the same. Thanks, Lakshmi On 31 May 2012 17:51, Johannes Schindelin <[hidden email]>wrote: >>> >>>> Hi Lakshmi, >>>> >>>> On Thu, 24 May 2012, Lakshmi Narjala wrote: >>>> >>>> > I placed the dll file in the directory that u said and I think I set >>>> > that path in the environment variables(though I am not sure if I did >>>> the >>>> > proper thing) I am still getting the same error.. what else needs to >>>> be >>>> > done? >>>> >>>> I actually forgot that there was an outstanding issue with the JNI >>>> support >>>> in Fiji on Windows. Probably the same thing that bit you; I just was >>>> able >>>> to fix it today (see https://github.com/fiji/fiji/commit/021185ce). >>>> >>>> I also wrote a very compressed introduction into JNI here: >>>> http://fiji.sc/JNI >>>> >>>> So here is my suggestion to get quickly to some working setup on >>>> Windows: >>>> Download and install msysgit from http://msysgit.github.com/, clone >>>> git://fiji.sc/fiji.git in msysgit and build it with "cd fiji && sh >>>> Build.sh". Then call "sh Build.sh plugins/JNI_Example.jar". >>>> >>>> To test it, run "./ImageJ --console", load the Clown example and run >>>> Plugins>JNI>JNI Example. In the console, you should see some statistics >>>> that were calculated by the C code. >>>> >>>> You can follow the JNI Example to implement your own plugin and follow >>>> the >>>> instructions at http://fiji.sc/Adding_Update_Sites to set up and >>>> populate >>>> your own update site with the result. >>>> >>>> Ciao, >>>> Johannes >>>> >>> >>> >> > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi Lakshmi,
On Wed, 6 Jun 2012, lakshmi narjala wrote: > Building plugins/JNI_Example.jar <- src-plugins/JNI_Example/plugin... > src-plugins/JNI_Example/JNI_Example.c:1:0: sorry, unimplemented: 64-bit > mode not compiled in That is a message of gcc saying that -m64 is unsupported, which is indeed the case for msysGit's gcc. However, msysGit has a convenience method to install mingw-w64's gcc which in a previous version supported the -m64 option (IIRC it is broken right now): have a look in /src/mingw-w64/. Ciao, Johannes -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Free forum by Nabble | Edit this page |