"Unsatisfied Link" exception when trying to use JNI

Discussion in 'Java' started by Dag Sunde, Jan 4, 2007.

  1. Dag Sunde

    Dag Sunde Guest

    I have the following Java class:

    package no.gaiasoft.fotoboks;
    public class Capture {
    // native method declaration
    native byte[] grabImage();
    // Load the library
    static {
    System.loadLibrary("canoncapture");
    }

    public static void main( String args[]) {
    byte buf[];
    Capture img = new Capture();
    buf = img.grabImage();
    String s = new String(buf);
    System.out.println(s);
    }
    }


    This I run thru javah to get this header file:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class no_gaiasoft_fotoboks_Capture */

    #ifndef _Included_no_gaiasoft_fotoboks_Capture
    #define _Included_no_gaiasoft_fotoboks_Capture
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
    * Class: no_gaiasoft_fotoboks_Capture
    * Method: grabImage
    * Signature: ()[B
    */
    JNIEXPORT jbyteArray JNICALL Java_no_gaiasoft_fotoboks_Capture_grabImage
    (JNIEnv *, jobject);

    #ifdef __cplusplus
    }
    #endif
    #endif


    I implement "canoncapture.dll" in visual studio like this:
    #include "stdafx.h"
    #include "jni.h"

    JNIEXPORT jbyteArray JNICALL Java_no_gaiasoft_fotoboks_Capture_grabImage
    (JNIEnv * env, jobject jobj) {

    jbyteArray jb;

    jb = env->NewByteArray(15);
    env->SetByteArrayRegion(jb,0,14, (jbyte *)'A');
    return (jb);
    }


    I put "canoncapture.dll" in java.library.path, and run Capture.
    this gives me the error:

    Exception in thread "main" java.lang.UnsatisfiedLinkError: grabImage
    at no.gaiasoft.fotoboks.Capture.grabImage(Native Method)
    at no.gaiasoft.fotoboks.Capture.main(Capture.java:17)

    Can anyone shed som light on what i might be doing wrong here?

    TIA...

    --
    Dag.

    Listen to your brain - it has a lot of information.
    (Chelsey, 7) -
    Dag Sunde, Jan 4, 2007
    #1
    1. Advertising

  2. On Thu, 4 Jan 2007 17:25:07 +0100, Dag Sunde wrote:
    > Exception in thread "main" java.lang.UnsatisfiedLinkError: grabImage
    > at no.gaiasoft.fotoboks.Capture.grabImage(Native Method)
    > at no.gaiasoft.fotoboks.Capture.main(Capture.java:17)
    >
    > Can anyone shed som light on what i might be doing wrong here?


    Your native source file doesn't seem to include the generated header
    file. That's important for the extern "C" declaration that prevents
    your C++ compiler from mangling the symbol names.

    After fixin that, confirm with a tool like dumpbin, depends or
    quickview that the symbol in the dll actually matches the generated
    name.

    /gordon

    --
    [ don't email me support questions or followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Jan 4, 2007
    #2
    1. Advertising

  3. Dag Sunde

    Dag Sunde Guest

    Gordon Beaton wrote:
    > On Thu, 4 Jan 2007 17:25:07 +0100, Dag Sunde wrote:
    >> Exception in thread "main" java.lang.UnsatisfiedLinkError: grabImage
    >> at no.gaiasoft.fotoboks.Capture.grabImage(Native Method)
    >> at no.gaiasoft.fotoboks.Capture.main(Capture.java:17)
    >>
    >> Can anyone shed som light on what i might be doing wrong here?

    >
    > Your native source file doesn't seem to include the generated header
    > file. That's important for the extern "C" declaration that prevents
    > your C++ compiler from mangling the symbol names.
    >
    > After fixin that, confirm with a tool like dumpbin, depends or
    > quickview that the symbol in the dll actually matches the generated
    > name.
    >


    Thanks!

    That led to progress! ;-)

    now i get:
    # An unexpected error has been detected by HotSpot Virtual Machine:
    #
    # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d76dc8a, pid=3488,
    tid=3432
    #
    # Java VM: Java HotSpot(TM) Client VM (1.5.0_06-b05 mixed mode)
    # Problematic frame:
    # V [jvm.dll+0x8dc8a]
    #
    # An error report file with more information is saved as hs_err_pid3488.log


    I'm on very thin ice when it comes to C/C++. Can this be because
    the C dll is compiled with a c++ compiler (MS VS 6.0)?

    ....or maybe I'm not up to speed concerning the mapping of datatypes.
    Will for example the statement:
    "env->SetByteArrayRegion(jb,0,14, (jbyte *)'A');"
    fill the jbyteArray with 15 'A' characters?


    TIA...

    --
    Dag.

    Listen to your brain - it has a lot of information.
    (Chelsey, 7) -
    Dag Sunde, Jan 4, 2007
    #3
  4. On Thu, 4 Jan 2007 18:05:02 +0100, Dag Sunde wrote:
    > Will for example the statement:
    > "env->SetByteArrayRegion(jb,0,14, (jbyte *)'A');"
    > fill the jbyteArray with 15 'A' characters?


    No.

    SetByteArrayRegion() takes a start and length, so the length of the
    region to fill is 14, not 15.

    Also, 'A' is a char, not an array. Attempting to treat it as a pointer
    is most likely the cause of your crash. You probably meant "A", which
    is an array of two characters ('A' followed by a terminating 0) and
    can be passed as a pointer.

    However, the array you pass to SetByteArrayRegion() needs as many
    elements as the number you specified, i.e. 14. So you'd need to pass
    "AAAAAAAAAAAAAA" for this to work as you intend. You might consider
    creating the native "AAA" buffer programmatically, or using
    SetByteArrayElement() to set the elements one at a time in a loop.

    /gordon

    --
    [ don't email me support questions or followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Jan 4, 2007
    #4
  5. Dag Sunde

    Dag Sunde Guest

    Gordon Beaton wrote:
    > On Thu, 4 Jan 2007 18:05:02 +0100, Dag Sunde wrote:
    >> Will for example the statement:
    >> "env->SetByteArrayRegion(jb,0,14, (jbyte *)'A');"
    >> fill the jbyteArray with 15 'A' characters?

    >
    > No.
    >
    > SetByteArrayRegion() takes a start and length, so the length of the
    > region to fill is 14, not 15.
    >
    > Also, 'A' is a char, not an array. Attempting to treat it as a pointer
    > is most likely the cause of your crash. You probably meant "A", which
    > is an array of two characters ('A' followed by a terminating 0) and
    > can be passed as a pointer.
    >
    > However, the array you pass to SetByteArrayRegion() needs as many
    > elements as the number you specified, i.e. 14. So you'd need to pass
    > "AAAAAAAAAAAAAA" for this to work as you intend. You might consider
    > creating the native "AAA" buffer programmatically, or using
    > SetByteArrayElement() to set the elements one at a time in a loop.
    >


    Gordon!

    You're a genius!

    Setting "AAAAAAAAAAAAAA" worked perfectly. But I can't find any
    method named SetByteArrayElement(), so I wasn't able to test that loop.

    On the other hand, I just needed to return something in a bytearray
    to get this skeleton up and running. The byte array will eventually
    be filled with jpeg data from a Canon PowerShot camera.

    You have my eternal gratitude (well... for a long time, anyway)!

    :)


    --
    Dag.

    Listen to your brain - it has a lot of information.
    (Chelsey, 7) -
    Dag Sunde, Jan 4, 2007
    #5
  6. On Thu, 4 Jan 2007 18:54:50 +0100, Dag Sunde wrote:
    > But I can't find any method named SetByteArrayElement(), so I wasn't
    > able to test that loop.


    My bad, I was thinking of SetObjectArrayElement() (which doesn't apply
    here).

    Another suggestion is to use GetByteArrayElements() to get a native
    array from the byte array, make any changes to the native
    array, then use ReleaseByteArrayElements() with JNI_COMMIT in order to
    propagate your changes back to the Java array.

    /gordon

    --
    [ don't email me support questions or followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Jan 4, 2007
    #6
  7. On Thu, 4 Jan 2007 18:54:50 +0100, Dag Sunde wrote:
    > The byte array will eventually be filled with jpeg data from a Canon
    > PowerShot camera.


    BTW are you aware of libgphoto? Apparently there are Java bindings.
    Base your application on that (except on Windows) and you'll be able
    to support hundreds of different cameras: http://www.gphoto.org/ .

    /gordon

    --
    [ don't email me support questions or followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Jan 4, 2007
    #7
  8. Dag Sunde

    Dag Sunde Guest

    Gordon Beaton wrote:
    > On Thu, 4 Jan 2007 18:54:50 +0100, Dag Sunde wrote:
    >> The byte array will eventually be filled with jpeg data from a Canon
    >> PowerShot camera.

    >
    > BTW are you aware of libgphoto? Apparently there are Java bindings.
    > Base your application on that (except on Windows) and you'll be able
    > to support hundreds of different cameras: http://www.gphoto.org/ .
    >

    Now, *That* is interesting!

    I convinced the customer to use Win2000 for the time being,
    because the selected camera and printer vendors have absolutely
    *no* support for U*ix, whatsoever. The customer really want this to run
    under Fedora core4/5 or Debian because of stability.

    Do you know if libgphoto have support for Remote Capture for
    the "Canon Powershot A640" camera?

    And have your ever heard of any Linux drivers for a
    "Mitsubishi 9559" printer too?
    :)

    --
    Dag.
    Dag Sunde, Jan 5, 2007
    #8
  9. Dag Sunde

    Dag Sunde Guest

    Dag Sunde wrote:
    > Gordon Beaton wrote:
    >> On Thu, 4 Jan 2007 18:54:50 +0100, Dag Sunde wrote:
    >>> The byte array will eventually be filled with jpeg data from a Canon
    >>> PowerShot camera.

    >>
    >> BTW are you aware of libgphoto? Apparently there are Java bindings.
    >> Base your application on that (except on Windows) and you'll be able
    >> to support hundreds of different cameras: http://www.gphoto.org/ .
    >>

    > Now, *That* is interesting!
    >
    > I convinced the customer to use Win2000 for the time being,
    > because the selected camera and printer vendors have absolutely
    > *no* support for U*ix, whatsoever. The customer really want this to
    > run under Fedora core4/5 or Debian because of stability.
    >
    > Do you know if libgphoto have support for Remote Capture for
    > the "Canon Powershot A640" camera?
    >
    > And have your ever heard of any Linux drivers for a
    > "Mitsubishi 9559" printer too?
    > :)


    A little bit triggerhappy there...

    I checked myself, and found that libgphoto2 2.3.0 have
    A640 support, but it isn't clear if it support the remote
    capture feature...

    --
    Dag.
    Dag Sunde, Jan 5, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mark
    Replies:
    9
    Views:
    695
    Steve W. Jackson
    Jan 16, 2004
  2. allelopath
    Replies:
    1
    Views:
    7,292
    P. Barthelemy
    Jan 4, 2005
  3. Replies:
    1
    Views:
    22,235
    Kari Ikonen
    Feb 6, 2005
  4. cppaddict
    Replies:
    4
    Views:
    20,180
    Gordon Beaton
    May 20, 2005
  5. Ten Blade
    Replies:
    5
    Views:
    895
    Roedy Green
    Jul 16, 2011
Loading...

Share This Page