0

Edit: Problem solved

I created a new project and imported the source files. (After trying too many options the project configuration was wrong.) It seems that I had confused the load and loadlibrary functions. load requires an absolute path including file postfix, e.g.:

static { System.load("c:/windows/system32/jnpout32.dll");}

When trying to call jnpout32.dll (http://www.hytherion.com/beattidp/comput/pport.htm) from Java in Eclipse (Windows 7, Java SE1.7) I receive the error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: EEGTrigger.ioPort.Out32(SS)V
at EEGTrigger.ioPort.Out32(Native Method)
at EEGTrigger.pPort.setAllDataBits(pPort.java:53)
at EEGTrigger.pPort.<init>(pPort.java:19)
at EEGTrigger.EEGTrigger.main(EEGTrigger.java:11)

The dll file is located in System32, in the src folder, and in C:\Users[user]\AppData\Local (as indicated by System.getenv())

In the Classpath under User entries, the file is also loaded

jnpout32.dll - \[Project]\src\[Project]\

and it is visible under Referenced Libraries in the Package Explorer

Both these lines do not work:

static { System.loadLibrary("jnpout32"); }
static { System.load("c:/windows/system32/jnpout32"); }

(.load as suggested in java.lang.UnsatisfiedLinkError - JNI)

I have confirmed that (based on java.lang.UnsatisfiedLinkError)

System.getProperty("java.library.path")

returns the system32 path.

The complete code of the java project (I have only authored the EEGTrigger class. The rest comes with the dll.):

package EEGTrigger;    

public class EEGTrigger {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Starting trigger...");

        pPort lpt1 = new pPort();


        testProtocol(lpt1);


    }

    private static void testProtocol(pPort lpt1) {
        // TODO Auto-generated method stub

        short selectTrigger = 0;

        sendPulse(lpt1, selectTrigger);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        selectTrigger = 1;
        sendPulse(lpt1, selectTrigger);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        selectTrigger = 2;
        sendPulse(lpt1, selectTrigger);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        selectTrigger = 3;
        sendPulse(lpt1, selectTrigger);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        selectTrigger = 4;
        sendPulse(lpt1, selectTrigger);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        selectTrigger = 0;
        sendPulse(lpt1, selectTrigger);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /**
     * @param lpt1
     */
    public static void sendPulse(pPort lpt1, short selectTrigger) {

        short trigger = 0;

        short targetTrigger = 255;
        short stimulusOnsetAsynchrony = 64;
        short trialOnsetTrigger = 32;
        short triggerOff = 0;

        switch (selectTrigger) { 
            case 1 :    trigger = targetTrigger;
                        break;

            case 2 :    trigger = stimulusOnsetAsynchrony;
                        break;

            case 3 :    trigger = trialOnsetTrigger;
                        break;

            case 4 :    trigger = triggerOff;
                        break;

            default :   trigger = triggerOff;
                        break;
        }

        lpt1.output(trigger);

        try {
            Thread.sleep(50);   // 50 milliseconds
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        lpt1.output(triggerOff);

    }

}


package EEGTrigger;

/* Definitions in the build of jnpout32.dll are:            */
/*   short _stdcall Inp32(short PortAddress);               */
/*   void _stdcall Out32(short PortAddress, short data);    */


public class ioPort
{
    // declare native methods of 'jnpout32.dll'

    // output a value to a specified port address
    public native void Out32(short PortAddress, short data);

    // input a value from a specified port address
    public native short Inp32(short PortAddress);

    // load 'jnpout32.dll'
    static { System.loadLibrary("jnpout32");}
    //static { System.load("c:/windows/system32/jnpout32"); }
}

package EEGTrigger;

// ** Derived from information provided on the web by Dr. Kenneth G. Schweller,
// ** ( http://web.bvu.edu/faculty/schweller/ ) and his Mars Rover project page.

public class pPort
{
   ioPort pp;                   // wrapper class for 'Jnpout32.dll'
                               // with methods:
                               //    int Out32(int port, int value);
                               //    int Inp32(int port);
   short portAddress;            // address of data port
   short currentVal;             // current value of port bits

   public pPort()
   {
      pp = new ioPort();
      portAddress = (short)0x378;     // Hex Address of Data Byte of PC Parallel Port
      setAllDataBits((short)0);       // initialize port bits to 0
      currentVal = 0x00;
   }

   // wrap ParallelPort output method
   public void output(short port, short value)
   {
      pp.Out32(port, value);
   }

   // wrap ParallelPort input method
   public short input(short port)
   {
      return pp.Inp32(port);
   }

    // output to default Data port
    public void output(short value)
    {
      pp.Out32(portAddress, value);
    }

    // input from default Data port
    public short input()
    {
      return pp.Inp32(portAddress);
    }


  /**
   * set all bits on Data port to zero
   **/
   public void setAllDataBits(short value)
   {
      pp.Out32(portAddress, value);
      currentVal = value;
   }


   // For users who prefer dealing with Pin numbers
   //    Set Pin <pin> to <value>
   public void setPin(short pin, short value)
   {
      if (pin >= 2 && pin <= 9)
         // just set the corresponding Data bit to indicted value
         setDataBit((short)(pin-2), value);
   }


   /**
    * Set Data Bit at selected index to a value of 1 or 0
    * while preserving current values of all other Data bits
    **/
   void setDataBit(short index, short value)
   {
      switch(index)
      {
         case 0:
           if (value==0)                        //  Set Data[0] to 0

              currentVal = (short) (currentVal & 0xFE);
                                                       //      aaaa aaaa  currentVal
                                                //  AND 1111 1110  mask
                                                //      =========
                                                //      aaaa aaa0  new currentVal

           else                                 //  Set Data[0] to 1

              currentVal = (short) (currentVal | 0x01);
                                                        //      aaaa aaaa   currentVal
                                                //  OR  0000 0001   mask
                                                //      =========
                                                //      aaaa aaa1   new currentVal
           break;
         case 1:
           if (value==0)
              currentVal = (short) (currentVal & 0xFD);
                                                        //  currentVal = aaaa aa0a
           else
              currentVal = (short) (currentVal | 0x02);
                                                        //  currentVal = aaaa aa1a
           break;
         case 2:
           if (value==0)
              currentVal = (short) (currentVal & 0xFB);
                                                        //  currentVal = aaaa a0aa
           else
              currentVal = (short) (currentVal | 0x04);
                                                        //  currentVal = aaaa a1aa
           break;
         case 3:
           if (value==1)
              currentVal = (short) (currentVal & 0xF7);
                                                        //  currentVal = aaaa 0aaa
           else
              currentVal = (short) (currentVal | 0x08);   //  currentVal = aaaa 1aaa
           break;
         case 4:
           if (value==0)
              currentVal = (short) (currentVal & 0xEF);
                                                        //  currentVal = aaa0 aaaa
           else
              currentVal = (short) (currentVal | 0x10);   //  currentVal = aaa1 aaaa
           break;
         case 5:
           if (value==0)
              currentVal = (short) (currentVal & 0xDF);
                                                        //  currentVal = aa0a aaaa
           else
              currentVal = (short) (currentVal | 0x20);   //  currentVal = aa1a aaaa
           break;
         case 6:
           if (value==0)
              currentVal = (short) (currentVal & 0xBF);
                                                        //  currentVal = a0aa aaaa
           else
              currentVal = (short) (currentVal | 0x40);   //  currentVal = a1aa aaaa
           break;
             case 7:
           if (value==0)
              currentVal = (short) (currentVal &  0x7F);
                                                        //  currentVal = 0aaa aaaa
           else
              currentVal = (short) (currentVal | 0x80);   //  currentVal = 1aaa aaaa
           break;

         default:
           System.out.println("index must be 0 - 7");
      }
      pp.Out32(portAddress, currentVal);
   }


}

The following questions were either not helpful or not applicable in this regard:

java.lang.UnsatisfiedLinkError

java.lang.UnsatisfiedLinkError

java.lang.UnsatisfiedLinkError

java.lang.UnsatisfiedLinkError

java.lang.UnsatisfiedLinkError in Linux

Java.lang.UnsatisfiedLinkError in eclipse

java.lang.UnsatisfiedLinkError: dbopen

JNI java.lang.UnsatisfiedLinkError

Community
  • 1
  • 1
noumenal
  • 1,077
  • 2
  • 16
  • 36

1 Answers1

0

You haven't provided very much information about why you might be getting an UnsatisfiedLinkError. Try attaching the full stack trace.

System.loadLibrary("jnpout32") is correct as long as java.library.path is set when the JVM starts via java -Djava.library.path="%WINDIR%/system32/"

If you want to use System.load, you should do something like System.load("c:/windows/system32/" + System.mapLibraryName("jnpout32")) to produce the native library name and extension.

If you are using them properly and both continue to fail, your error is somewhere else like a dependent library that is missing.

Alex Barker
  • 4,316
  • 4
  • 28
  • 47
  • Added complete stack trace to post. After adding the command that you suggested to the VM arguments Eclipse returns "...no jnpout32 in java.library.path...". Using C:/Windows instead of %WINDIR% returns the previous error. – noumenal Jul 01 '14 at 12:33
  • 1
    The error still remains in the project even though I commented out the line causing it. There seems to be a bug in Eclipse. – noumenal Jul 01 '14 at 13:04