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