【问题标题】:DLL Call From Java Returns an UnsatisfiedLinkError来自 Java 的 DLL 调用返回 UnsatisfiedLinkError
【发布时间】:2014-08-18 08:49:18
【问题描述】:

编辑:问题已解决

我创建了一个新项目并导入了源文件。 (在尝试了太多选项后,项目配置错误。)似乎我混淆了 load 和 loadlibrary 功能。 load 需要包含文件后缀的绝对路径,例如:

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

尝试在 Eclipse(Windows 7、Java SE1.7)中从 Java 调用 jnpout32.dll (http://www.hytherion.com/beattidp/comput/pport.htm) 时收到错误消息:

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)

dll 文件位于 System32、src 文件夹和 C:\Users[user]\AppData\Local 中(如 System.getenv() 所示)

在用户条目下的类路径中,该文件也被加载

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

并且它在 Package Explorer 中的 Referenced Libraries 下可见

这两行都不起作用:

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

(按照java.lang.UnsatisfiedLinkError - JNI中的建议加载)

我已经确认(基于java.lang.UnsatisfiedLinkError

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

返回 system32 路径。

java项目的完整代码(我只编写了EEGTrigger类,其余的都是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);
   }


}

以下问题在这方面没有帮助或不适用:

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

【问题讨论】:

    标签: java eclipse dll java-native-interface


    【解决方案1】:

    您没有提供太多关于为什么您可能会收到 UnsatisfiedLinkError 的信息。尝试附加完整的堆栈跟踪。

    只要在JVM启动时通过java -Djava.library.path="%WINDIR%/system32/"设置了java.library.path,System.loadLibrary("jnpout32")就是正确的

    如果您想使用 System.load,您应该执行类似 System.load("c:/windows/system32/" + System.mapLibraryName("jnpout32")) 的操作来生成本机库名称和扩展名。

    如果您正确使用它们并且两者都继续失败,那么您的错误就在其他地方,例如缺少依赖库。

    【讨论】:

    • 添加了完整的堆栈跟踪来发布。将您建议的命令添加到 VM 参数后,Eclipse 将返回“...no jnpout32 in java.library.path ...”。使用 C:/Windows 而不是 %WINDIR% 会返回上一个错误。
    • 即使我注释掉了导致它的行,该错误仍然存​​在于项目中。 Eclipse 中似乎有一个错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多