Assistance Required

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Assistance Required

lakshmi
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
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

dscho
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
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

lakshmi
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
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

dscho
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
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

dscho
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
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

lakshmi
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?
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

ctrueden
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
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

dscho
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
Reply | Threaded
Open this post in threaded view
|

Assistance Required

lakshmi
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
Reply | Threaded
Open this post in threaded view
|

Re: Assistance Required

dscho
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