diff --git a/src/eva2/tools/matlab/JMatLink.java b/src/eva2/tools/matlab/JMatLink.java index 98cc07f1..34940ae6 100644 --- a/src/eva2/tools/matlab/JMatLink.java +++ b/src/eva2/tools/matlab/JMatLink.java @@ -1,62 +1,60 @@ /***************************************************************************** -* JMatLink * + * JMatLink * -****************************************************************************** + ****************************************************************************** -* (c) 1999-2001 Stefan Mueller (email: stefan@held-mueller.de) * + * (c) 1999-2001 Stefan Mueller (email: stefan@held-mueller.de) * -****************************************************************************** + ****************************************************************************** -* 19.01.1999 beginning (reuse of HelloWorld example, Java Tutorial) (0.01) * + * 19.01.1999 beginning (reuse of HelloWorld example, Java Tutorial) (0.01) * -* 06.02.1999 separation from gui (0.02) * + * 06.02.1999 separation from gui (0.02) * -* 27.03.1999 engGetScalar, engGetVector, engGetArray (0.03) * + * 27.03.1999 engGetScalar, engGetVector, engGetArray (0.03) * -* 02.05.1999 engGetScalar already works * + * 02.05.1999 engGetScalar already works * -* 20.05.1999 deleted engPutArray (float..., int...) (0.04) * + * 20.05.1999 deleted engPutArray (float..., int...) (0.04) * -* 13.08.1999 thread implementation due to ActiveX thread problem (0.05) * + * 13.08.1999 thread implementation due to ActiveX thread problem (0.05) * -* 15.08.1999 intruduced 2 locking mechanisms to lock the engine and * + * 15.08.1999 intruduced 2 locking mechanisms to lock the engine and * -* wait for data to be return to caller. (0.06) * + * wait for data to be return to caller. (0.06) * -* 16.08.1999 wait for all engine calls to return savely (0.06a)* + * 16.08.1999 wait for all engine calls to return savely (0.06a)* -* 29.08.1999 made all engine routines "synchronized" (0.07) * + * 29.08.1999 made all engine routines "synchronized" (0.07) * -* 11.09.1999 get char array from workspace (0.08) * + * 11.09.1999 get char array from workspace (0.08) * -* 21.09.1999 engGetCharArray working (conversion to double matrix first) * + * 21.09.1999 engGetCharArray working (conversion to double matrix first) * -* (transfer as double throught engine and conversion * + * (transfer as double throught engine and conversion * -* back to double) engine doesn't support char arrays (0.09) * + * back to double) engine doesn't support char arrays (0.09) * -* 10.10.1999 engPutArray(String name, double[][] values) (0.10) * + * 10.10.1999 engPutArray(String name, double[][] values) (0.10) * -* 04/07/2001 restart work on JMatLink (0.11) * + * 04/07/2001 restart work on JMatLink (0.11) * -* 05/24/2001 engOpenSingleUse (0.11) * + * 05/24/2001 engOpenSingleUse (0.11) * -* 05/24/2001 engClose(int pointer) (0.11) * + * 05/24/2001 engClose(int pointer) (0.11) * -* 06/04/2001 engEvalString(ep, evalString) * + * 06/04/2001 engEvalString(ep, evalString) * -* 06/10/2001 use of maximum number of arguments of all engine functions * + * 06/10/2001 use of maximum number of arguments of all engine functions * -* 07/31/2001 setDebug() to suppress messages to the console window * + * 07/31/2001 setDebug() to suppress messages to the console window * -* 08/09/2001 extensive documentation * - -* 08/09/2001 final version. upgrade version number (1.00) * - -******************************************************************************/ + * 08/09/2001 extensive documentation * + * 08/09/2001 final version. upgrade version number (1.00) * + ******************************************************************************/ //**************************************************************************** @@ -82,46 +80,38 @@ //**************************************************************************** - - - - /** ToDo list -* engOpen is supposed to throw an exception if not successfull + * engOpen is supposed to throw an exception if not successfull -* I'm not sure what happens if large matrices are passed back and + * I'm not sure what happens if large matrices are passed back and - force between this class and other applications. Maybe I + force between this class and other applications. Maybe I - should always clear all global arrays engGetArray1dD... + should always clear all global arrays engGetArray1dD... -* I'm not sure if the locking mechanism is good or bad. There + * I'm not sure if the locking mechanism is good or bad. There - may be a problem, if two subsequent calls to two different + may be a problem, if two subsequent calls to two different - engine routines occur at the same time. + engine routines occur at the same time. -* what should I do with the return values of the engine functions? Throw + * what should I do with the return values of the engine functions? Throw - an exception? + an exception? -* make engPutArray also for int, + * make engPutArray also for int, -* make engGetArray/Scalar also for int + * make engGetArray/Scalar also for int -* make engGetCharArray also for different engine pointers - -* make something like engGetOutputBuffer - -*/ + * make engGetCharArray also for different engine pointers + * make something like engGetOutputBuffer + */ package eva2.tools.matlab; - - // **** Thread programming. Notify and start and stop **** // Look at @@ -133,1883 +123,1664 @@ package eva2.tools.matlab; // The problem is ActiveX: one only can make calls to the engine library // (especially engEvalString) from ONE single thread. -import java.io.*; +import java.io.UnsupportedEncodingException; -import eva2.tools.tool.*; public class JMatLink extends Thread { - private static JMatLink m_Instance = null; - /** + private static JMatLink m_Instance = null; + + /** * */ - public static JMatLink getInstance () { - //System.out.println("JMatLink getInstance () {"); - if (m_Instance==null) - m_Instance = new JMatLink(); - return m_Instance; - } - // static declarations - // the variable "status" is used to tell the main - // thread what to do. - private final static int idleI = 0; - private final static int engOpenI = 1; - private final static int engCloseI = 2; - private final static int engEvalStringI = 3; - private final static int engGetScalarI = 4; - private final static int engGetVectorI = 5; - private final static int engGetArrayI = 6; - private final static int engPutArray2dI = 9; - private final static int engOutputBufferI = 10; - private final static int engGetCharArrayI = 11; - private final static int destroyJMatLinkI = 12; - private final static int engOpenSingleUseI = 13; - // All variables are global to allow all methods + public static JMatLink getInstance() { + // System.out.println("JMatLink getInstance () {"); + if (m_Instance == null) + m_Instance = new JMatLink(); + return m_Instance; + } - // and the main thread to share all data + // static declarations + // the variable "status" is used to tell the main + // thread what to do. + private final static int idleI = 0; + private final static int engOpenI = 1; + private final static int engCloseI = 2; + private final static int engEvalStringI = 3; + private final static int engGetScalarI = 4; + private final static int engGetVectorI = 5; + private final static int engGetArrayI = 6; + private final static int engPutArray2dI = 9; + private final static int engOutputBufferI = 10; + private final static int engGetCharArrayI = 11; + private final static int destroyJMatLinkI = 12; + private final static int engOpenSingleUseI = 13; + // All variables are global to allow all methods - private int status = idleI; + // and the main thread to share all data - private String arrayS; + private int status = idleI; - private String engEvalStringS; + private String arrayS; - private String engOutputBufferS; + private String engEvalStringS; - private double engGetScalarD; + private String engOutputBufferS; - private double[] engGetVectorD; + private double engGetScalarD; - private double[][] engGetArrayD; + private double[] engGetVectorD; - private double engPutArrayD; + private double[][] engGetArrayD; - private double[] engPutArray1dD; + private double engPutArrayD; - private double[][] engPutArray2dD; + private double[] engPutArray1dD; - private String[] engGetCharArrayS; + private double[][] engPutArray2dD; - private int epI; /* Engine pointer */ + private String[] engGetCharArrayS; - private int retValI; /* return Value of eng-methods */ + private int epI; /* Engine pointer */ - private String startCmdS; /* start command for engOpen... */ + private int retValI; /* return Value of eng-methods */ - private int buflenI; /* output buffer length */ + private String startCmdS; /* start command for engOpen... */ - private boolean debugB = false; + private int buflenI; /* output buffer length */ + private boolean debugB = false; + // Locks - // Locks + private boolean lockEngineB = false; - private boolean lockEngineB = false; + private boolean lockThreadB = false; - private boolean lockThreadB = false; + private boolean lockWaitForValueB = false; - private boolean lockWaitForValueB = false; + private boolean destroyJMatLinkB = false; - private boolean destroyJMatLinkB = false; + private Thread runner; + // *********************** native declarations **************************** + // NEVER call native methods directly, like - private Thread runner; + // JMatLink.engEvalStringNATIVE("a=1"). Matlab's engine has quite some + // thread problems. + private native void displayHelloWorld(); - // *********************** native declarations **************************** + private native void engTestNATIVE(); - // NEVER call native methods directly, like + private native int engOpenNATIVE(String startCmdS); - // JMatLink.engEvalStringNATIVE("a=1"). Matlab's engine has quite some + private native int engOpenSingleUseNATIVE(String startCmdS); - // thread problems. + private native int engCloseNATIVE(int epI); - private native void displayHelloWorld(); + private native int engEvalStringNATIVE(int epI, String evalS); - private native void engTestNATIVE(); + private native double engGetScalarNATIVE(int epI, String nameS); + private native double[] engGetVectorNATIVE(int epI, String nameS); + private native double[][] engGetArrayNATIVE(int epI, String nameS); - private native int engOpenNATIVE (String startCmdS ); + private native String[] engGetCharArrayNATIVE(int epI, String nameS); - private native int engOpenSingleUseNATIVE (String startCmdS ); + private native void engPutArrayNATIVE(int epI, String matrixS, + double[][] valuesDD); + private native String engOutputBufferNATIVE(int epI, int buflenI); + private native void setDebugNATIVE(boolean debugB); - private native int engCloseNATIVE (int epI); + // ******************************************************************************* + // ************** load JMatLink library into memory ********************** + static { + // System.out.println("loading !!"); + try { // System.out.println("loading"); - private native int engEvalStringNATIVE (int epI, String evalS ); + System.loadLibrary("JMatLink"); + // String + // path="../lib/"+SystemHelper.getOperationSystemName()+"/JMatLink.dll"; + // System.out.println("load: "+path); - private native double engGetScalarNATIVE (int epI, String nameS ); + // System.loadLibrary(path); - private native double[] engGetVectorNATIVE (int epI, String nameS ); + // String libPath = "." + System.getProperty("file.separator", "/"); - private native double[][] engGetArrayNATIVE (int epI, String nameS ); + // //libPath += SystemHelper.getOperationSystemName() + + // System.getProperty("file.separator", "/"); - private native String[] engGetCharArrayNATIVE (int epI, String nameS ); + // libPath += System.mapLibraryName("JMatLink"); + // + // // make sure that we have the absolute path - private native void engPutArrayNATIVE (int epI, String matrixS, double[][] valuesDD); + // libPath = new File(libPath).getAbsolutePath(); + // + // System.out.println("load: "+"d:/workingAt/JCompChem/lib/windows/JMatLink.dll"); - private native String engOutputBufferNATIVE (int epI, int buflenI ); + // System.loadLibrary("../lib/windows/JMatLink_old.dll"); + // System.out.println("loaded"); + } - private native void setDebugNATIVE (boolean debugB ); + catch (UnsatisfiedLinkError e) { + System.err.println("ERROR: Could not load the JMatLink library"); + e.printStackTrace(); - // ******************************************************************************* + } + // System.out.println("loading !! end"); - // ************** load JMatLink library into memory ********************** + } - static { - //System.out.println("loading !!"); - try { //System.out.println("loading"); + // ************************ JMatLink constructor *************************** - System.loadLibrary("JMatLink"); + /** + * This is the constructor for the JMatLink library. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("surf(peaks)");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + private JMatLink() { -// String path="../lib/"+SystemHelper.getOperationSystemName()+"/JMatLink.dll"; + if (debugB) + System.out.println("JMatLink constructor"); -// System.out.println("load: "+path); + runner = new Thread(this); -// System.loadLibrary(path); + runner.start(); + } + // **** terminate running thread **** -// String libPath = "." + System.getProperty("file.separator", "/"); + public void destroy() { -// //libPath += SystemHelper.getOperationSystemName() + System.getProperty("file.separator", "/"); + destroyJMatLinkB = true; -// libPath += System.mapLibraryName("JMatLink"); + notifyAll(); -// + } -// // make sure that we have the absolute path + public void kill() { -// libPath = new File(libPath).getAbsolutePath(); + destroyJMatLinkB = true; -// + callThread(destroyJMatLinkI); -// System.out.println("load: "+"d:/workingAt/JCompChem/lib/windows/JMatLink.dll"); + } -// System.loadLibrary("../lib/windows/JMatLink_old.dll"); + // //////////////////////////////////////////////////////////////////////////// - //System.out.println("loaded"); + // ***************************** engOpen ***************************** - } + /** + * Open engine. This command is used to open a single connection + * + * to matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("surf(peaks)");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ - catch (UnsatisfiedLinkError e) { + public synchronized int engOpen() - System.err.println("ERROR: Could not load the JMatLink library"); + { + return engOpen(""); // return value is pointer to engine - e.printStackTrace(); + } + + // ***************************** engOpen ******************************* + + /** + * Open engine. This command is used to open a single connection + * + * to matlab. + *

+ * This command is only useful on unix systems. On windows + * + * the optional parameter must be NULL. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen("commands to start matlab");
+	 * 
+	 *   engine.engEvalString("surf(peaks)");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized int engOpen(String startCmdS) + + { + + // startup MATLAB and set up connection + + lockEngineLock(); + + lockWaitForValue(); + + this.startCmdS = startCmdS; + + callThread(engOpenI); + + WaitForValue(); + + releaseEngineLock(); + + return this.epI; + + } + + // ************************** engOpenSingleUse ***************************** + + /** + * Open engine for single use. This command is used to open + * + * multiple connections to matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   int a,b;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   a = engine.engOpenSingleUse();   // start first matlab session
+	 * 
+	 *   b = engine.engOpenSingleUse();   // start second matlab session
+	 * 
+	 *   engine.engEvalString(a, "surf(peaks)");
+	 * 
+	 *   engine.engEvalString(b, "foo=ones(10,0)");
+	 * 
+	 *   engine.engClose(a);
+	 * 
+	 *   engine.engClose(b);
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized int engOpenSingleUse() + + { + + return engOpenSingleUse(""); + + } + + // ************************** engOpenSingleUse ***************************** + + /** + * Open engine for single use. This command is used to open + * + * multiple connections to matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   int a,b;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   a = engine.engOpenSingleUse("start matlab");   // start first matlab session
+	 * 
+	 *   b = engine.engOpenSingleUse("start matlab");   // start second matlab session
+	 * 
+	 *   engine.engEvalString(a, "surf(peaks)");
+	 * 
+	 *   engine.engEvalString(b, "foo=ones(10,0)");
+	 * 
+	 *   engine.engClose(a);
+	 * 
+	 *   engine.engClose(b);
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized int engOpenSingleUse(String startCmdS) + + { + + lockEngineLock(); + + lockWaitForValue(); + + this.startCmdS = startCmdS; + + callThread(engOpenSingleUseI); + + WaitForValue(); + + releaseEngineLock(); + + return this.epI; + + } + + // ***************************** engClose ***************************** + + /** + * Close the connection to matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *  JMatLink engine = new JMatLink();
+	 * 
+	 *  engine.engOpen();
+	 * 
+	 *  engine.engEvalString("surf(peaks)");
+	 * 
+	 *  engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engClose() + + { + + engClose(this.epI); + + } + + // ***************************** engClose ***************************** + + /** + * Close a specified connection to an instance of matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *  int a,b;
+	 * 
+	 *  JMatLink engine = new JMatLink();
+	 * 
+	 *  a = engine.engOpenSingleUse();       // start first  matlab session
+	 * 
+	 *  b = engine.engOpenSingleUse();       // start second matlab session
+	 * 
+	 *  engine.engEvalString(b, "surf(peaks)");
+	 * 
+	 *  engine.engEvalString(a, "array = randn(23)");
+	 * 
+	 *  engine.engClose(a);      // Close the first  connection to matlab
+	 * 
+	 *  engine.engClose(b);      // Close the second connection to matlab
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engClose(int epI) + + { - } - //System.out.println("loading !! end"); + // close connection and terminate MATLAB - } + lockEngineLock(); + lockWaitForValue(); + this.epI = epI; + callThread(engCloseI); + WaitForValue(); - // ************************ JMatLink constructor *************************** + releaseEngineLock(); - /** This is the constructor for the JMatLink library. + // return retValI; Return value indicates success - * + } - *

E.g.:
+ // ***************************** engEvalString ***************************** - *

+	/**
+	 * Evaluate an expression in matlab's workspace.
+	 * 
+	 * 
+	 * 
+	 * E.g.:
+ * + *
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("surf(peaks)");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engEvalString(String evalS) + + { + + engEvalString(this.epI, evalS); + + } + + // ***************************** engEvalString ************************* + + /** + * Evaluate an expression in a specified workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *  int a,b;
+	 * 
+	 *  JMatLink engine = new JMatLink();
+	 * 
+	 *  a = engine.engOpenSingleUse();
+	 * 
+	 *  engine.engEvalString(a, "surf(peaks)");
+	 * 
+	 *  engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engEvalString(int epI, String evalS) + + { + + // evaluate expression "evalS" in specified engine Ep + + if (debugB) + System.out.println("eval(ep,String) in " + epI + " " + evalS); + + lockEngineLock(); - * JMatLink engine = new JMatLink(); + lockWaitForValue(); - * engine.engOpen(); + this.epI = epI; - * engine.engEvalString("surf(peaks)"); + engEvalStringS = evalS; - * engine.engClose(); + callThread(engEvalStringI); - *
+ WaitForValue(); - ***************************************************************************/ + releaseEngineLock(); - private JMatLink() { + if (debugB) + System.out.println("eval(ep,String) out " + epI + " " + evalS); - if (debugB) System.out.println("JMatLink constructor"); + // return retValI; Return value indicates success - runner = new Thread(this); + } - runner.start(); + // ***************************** engGetScalar ************************** - } + /** + * Get a scalar value from matlab's workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *  double a;
+	 * 
+	 *  JMatLink engine = new JMatLink();
+	 * 
+	 *  engine.engOpen();
+	 * 
+	 *  engine.engEvalString("foo = sin( 3 )");
+	 * 
+	 *  a = engine.engGetScalarValue("foo");
+	 * 
+	 *  engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized double engGetScalar(String arrayS) + { + return engGetScalar(this.epI, arrayS); - // **** terminate running thread **** + } - public void destroy() { + // ***************************** engGetScalar ************************** - destroyJMatLinkB = true; + /** + * Get a scalar value from a specified workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   double a;
+	 * 
+	 *   int b;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   b = engine.engOpenSigleUse();
+	 * 
+	 *   engine.engEvalString(b, "foo = sin( 3 )");
+	 * 
+	 *   a = engine.engGetScalarValue(b, "foo");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized double engGetScalar(int epI, String arrayS) - notifyAll(); + { - } + // Get scalar value or element (1,1) of an array from + // MATLAB's workspace + // Only real values are supported right now - public void kill() { + lockEngineLock(); - destroyJMatLinkB = true; + lockWaitForValue(); - callThread(destroyJMatLinkI); + /* copy parameters to global variables */ - } + this.epI = epI; + this.arrayS = arrayS; + callThread(engGetScalarI); -////////////////////////////////////////////////////////////////////////////// + WaitForValue(); + releaseEngineLock(); + + return engGetScalarD; + + } + + // ***************************** engGetVector ************************** + + /** + * Get an array (1 * n) from matlab's workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   double[] array;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("array = randn(10,1);");
+	 * 
+	 *   array = engine.engGetVector("array");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized double[] engGetVector(String arrayS) + + { + + return engGetVector(this.epI, arrayS); + + } + + // ***************************** engGetVector ************************** + + /** + * Get an array (1 * n) from a specified workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   int b;
+	 * 
+	 *   double[] array;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   b = engine.engOpenSingleUse();
+	 * 
+	 *   engine.engEvalString(b, "array = randn(10,1);");
+	 * 
+	 *   array = engine.engGetVector(b, "array");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized double[] engGetVector(int epI, String arrayS) + { + // only real values are supported so far + lockEngineLock(); - // ***************************** engOpen ***************************** + lockWaitForValue(); - /** Open engine. This command is used to open a single connection + this.epI = epI; - * to matlab. + this.arrayS = arrayS; - * + callThread(engGetVectorI); - *

E.g.:
+ WaitForValue(); - *

+		releaseEngineLock();
 
-    *   JMatLink engine = new JMatLink();
+		return engGetVectorD;
+
+	}
+
+	// ***************************** engGetArray ***************************
+
+	/**
+	 * Get an array from matlab's workspace.
+	 * 
+	 * 
+	 * 
+	 * 

+ * E.g.:
+ * + *

+	 * 
+	 *   int b;
+	 * 
+	 *   double[][] array;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("array = randn(10);");
+	 * 
+	 *   array = engine.engGetArray("array");
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized double[][] engGetArray(String arrayS) + + { + + return engGetArray(this.epI, arrayS); + + } - * engine.engOpen(); + // ***************************** engGetArray *************************** - * engine.engEvalString("surf(peaks)"); + /** + * Get an array from a specified instance/workspace of matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   int b;
+	 * 
+	 *   double[][] array;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   b = engine.engOpenSingleUse();
+	 * 
+	 *   engine.engEvalString(b, "array = randn(10);");
+	 * 
+	 *   array = engine.engGetArray(b, "array");
+	 * 
+	 *   engine.engClose(b);
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized double[][] engGetArray(int epI, String arrayS) + + { - * engine.engClose(); + // only real values are supported so far - *
+ lockEngineLock(); - ***************************************************************************/ + lockWaitForValue(); - public synchronized int engOpen() + this.epI = epI; - { - return engOpen( "" ); // return value is pointer to engine + this.arrayS = arrayS; - } + callThread(engGetArrayI); + WaitForValue(); + releaseEngineLock(); + return engGetArrayD; + } - // ***************************** engOpen ******************************* + // ************************** engGetCharArray ***************************** - /** Open engine. This command is used to open a single connection + /** + * Get an 'char' array (string) from matlab's workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   String array;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("array = 'hello world';");
+	 * 
+	 *   array = engine.engCharArray("array");
+	 * 
+	 *   System.out.println("output = "+ array);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ - * to matlab.

This command is only useful on unix systems. On windows + public synchronized String[] engGetCharArray(String arrayS) - * the optional parameter must be NULL. + { - * + // convert to double array - *

E.g.:
+ engEvalString("engGetCharArrayD=double(" + arrayS + ")"); - *

+		// get double array
 
-    *   JMatLink engine = new JMatLink();
+		double[][] arrayD = engGetArray("engGetCharArrayD");
+
+		// delete temporary double array
+
+		engEvalString("clear engGetCharArrayD");
+
+		// convert double back to char
+
+		return double2String(arrayD);
+
+	}
+
+	// ***************************** engPutArray ***************************
+
+	/**
+	 * Put an array into a specified workspace.
+	 * 
+	 * 
+	 * 
+	 * 

+ * E.g.:
+ * + *

+	 * 
+	 *   int array = 1;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engPutArray("array", array);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ - * engine.engOpen("commands to start matlab"); + public synchronized void engPutArray(String arrayS, int valueI) - * engine.engEvalString("surf(peaks)"); + { - * engine.engClose(); + engPutArray(this.epI, arrayS, new Integer(valueI).doubleValue()); + + } + + // ***************************** engPutArray *************************** + + // public synchronized void engPutArray( String arrayS, int[] valuesI ) + + // { + + // engPutArray( this.epI, arrayS, (double[])valuesI ); + + // } + + // ***************************** engPutArray *************************** + + /** + * Put an array into matlab's workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   double array = 1;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engPutArray("array", array);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engPutArray(String arrayS, double valueD) + + { + + engPutArray(this.epI, arrayS, valueD); + + } + + // ***************************** engPutArray ***************************** + + /** + * Put an array into a specified instance/workspace of matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   int b;
+	 * 
+	 *   double array = 1;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   b = engine.engOpenSingleUse();
+	 * 
+	 *   engine.engPutArray(b, "array", array);
+	 * 
+	 *   engine.engClose(b);
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engPutArray(int epI, String arrayS, double valueD) + + { + + double vDD[][] = { { 0.0 } }; + + vDD[0][0] = valueD; + + engPutArray(epI, arrayS, vDD); // nxn dimensional + + } + + // ***************************** engPutArray *************************** + + /** + * Put an array (1 dimensional) into a specified instance/workspace of + * + * matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   double[] array = {1.0 , 2.0 , 3.0};
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engPutArray("array", array);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engPutArray(String arrayS, double[] valuesD) + + { + + engPutArray(this.epI, arrayS, valuesD); + + } + + // ***************************** engPutArray ***************************** + + /** + * Put an array (1 dimensional) into a specified instance/workspace of + * + * matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   int b;
+	 * 
+	 *   double[] array = {1.0 , 2.0 , 3.0};
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   b = engine.engOpenSingleUse();
+	 * 
+	 *   engine.engPutArray(b, "array", array);
+	 * 
+	 *   engine.engClose(b);
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engPutArray(int epI, String arrayS, + double[] valuesD) + + { + + double[][] vDD = new double[1][valuesD.length]; // 1xn array + + if (debugB) + System.out.println("length = " + valuesD.length); + + vDD[0] = valuesD; // copy row + + engPutArray(epI, arrayS, vDD); + + } + + // ***************************** engPutArray *************************** + + /** + * Put an array (2 dimensional) into matlab's workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   double[][] array={{1.0 , 2.0 , 3.0},
+	 * 
+	 *                     {4.0 , 5.0 , 6.0}};
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpenSingleUse();
+	 * 
+	 *   engine.engPutArray("array", array);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engPutArray(String arrayS, double[][] valuesDD) + + { + + engPutArray(this.epI, arrayS, valuesDD); + + } + + // ***************************** engPutArray *************************** + + /** + * Put an array (2 dimensional) into a specified instance/workspace of + * + * matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 * int b;
+	 * 
+	 * double[][] array = { { 1.0, 2.0, 3.0 },
+	 * 
+	 * { 4.0, 5.0, 6.0 } };
+	 * 
+	 * JMatLink engine = new JMatLink();
+	 * 
+	 * b = engine.engOpenSingleUse();
+	 * 
+	 * engine.engPutArray(b, "array", array);
+	 * 
+	 * engine.engClose(b);
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized void engPutArray(int epI, String arrayS, + double[][] valuesDD) + + { + + // send an array to MATLAB + + // only real values are supported so far + + lockEngineLock(); + + lockWaitForValue(); + + this.epI = epI; + + this.arrayS = arrayS; + + this.engPutArray2dD = valuesDD; + + callThread(engPutArray2dI); + + WaitForValue(); + + releaseEngineLock(); + + } + + // ***************************** engOutputBuffer *********************** + + /** + * Return the outputs of previous commands from matlab's workspace. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   String buffer;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("surf(peaks)");
+	 * 
+	 *   buffer = engine.engOutputBuffer();
+	 * 
+	 *   System.out.println("workspace " + buffer);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized String engOutputBuffer() + + { + + return engOutputBuffer(this.epI, this.buflenI); + + } + + // ***************************** engOutputBuffer *********************** + + /** + * Return the outputs of previous commands from a specified instance/ + * + * workspace form matlab. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   String buffer;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("surf(peaks)");
+	 * 
+	 *   buffer = engine.engOutputBuffer();
+	 * 
+	 *   System.out.println("workspace " + buffer);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized String engOutputBuffer(int epI) + + { + + return engOutputBuffer(epI, this.buflenI); + + } + + // ***************************** engOutputBuffer *********************** + + /** + * Return the ouputs of previous commands in matlab's workspace. + * + * + * + * Right now the parameter buflen is not supported. + * + * + * + *

+ * E.g.:
+ * + *

+	 * 
+	 *   String buffer;
+	 * 
+	 *   JMatLink engine = new JMatLink();
+	 * 
+	 *   engine.engOpen();
+	 * 
+	 *   engine.engEvalString("surf(peaks)");
+	 * 
+	 *   buffer = engine.engOutputBuffer();
+	 * 
+	 *   System.out.println("workspace " + buffer);
+	 * 
+	 *   engine.engClose();
+	 * 
+	 * 
+ ***************************************************************************/ + + public synchronized String engOutputBuffer(int epI, int buflenI) - *
+ { - ***************************************************************************/ + // get the output buffer from MATLAB - public synchronized int engOpen(String startCmdS) + if (debugB) + System.out + .println("Thread in: " + Thread.currentThread().getName()); - { + lockEngineLock(); - // startup MATLAB and set up connection + lockWaitForValue(); - lockEngineLock(); + this.epI = epI; - lockWaitForValue(); + this.buflenI = buflenI; + callThread(engOutputBufferI); + WaitForValue(); - this.startCmdS = startCmdS; + releaseEngineLock(); + if (debugB) + System.out.println("Thread out: " + + Thread.currentThread().getName()); + return engOutputBufferS; - callThread( engOpenI ); + } + // ***************************** setDebug ******************************* + /* + * Switch on or disable debug information printed to standard output. + * + * + * + *

Default setting is debug info disabled. + * + *

E.g.:
+ * + *

+	 * 
+	 * JMatLink engine = new JMatLink();
+	 * 
+	 * engine.engOpenSingleUse();
+	 * 
+	 * engine.setDebug(true);
+	 * 
+	 * engine.engEvalString("a=ones(10,5);");
+	 * 
+	 * engine.engClose();
+	 * 
+	 * 
+ * + * ************************************************************************* + */ - WaitForValue(); + public void setDebug(boolean debugB) - releaseEngineLock(); + { + this.debugB = debugB; + setDebugNATIVE(debugB); - return this.epI; + } - } + // ////////////////////////////////////////////////////////////////////////////// + // This method notifys the main thread to call matlab's engine + // Since threads don't have methods, we set a variable which + // contains the necessary information about what to do. + private synchronized void callThread(int status) - // ************************** engOpenSingleUse ***************************** + { - /** Open engine for single use. This command is used to open + this.status = status; - * multiple connections to matlab. + lockThreadB = false; - * + notifyAll(); - *

E.g.:
+ } - *

+	// //////////////////////////////////////////////////////////////////////////////
 
-    *   int a,b;
+	// The run methods does ALL calls to the native methods
 
-    *   JMatLink engine = new JMatLink();
+	// The keyword "synchronized" is neccessary to block the run()
 
-    *   a = engine.engOpenSingleUse();   // start first matlab session
+	// method as long as one command needs to get executed.
 
-    *   b = engine.engOpenSingleUse();   // start second matlab session
+	public synchronized void run()
 
-    *   engine.engEvalString(a, "surf(peaks)");
+	{
 
-    *   engine.engEvalString(b, "foo=ones(10,0)");
+		int tempRetVal;
 
-    *   engine.engClose(a);
+		if (debugB)
+			System.out.println("JMatLink: thread is running");
 
-    *   engine.engClose(b);
+		while (true) {
 
-    * 
+ // System.out.println("Number of Java-Threads: "+Thread.activeCount()+""); - ***************************************************************************/ + // Thread thread = Thread.currentThread(); - public synchronized int engOpenSingleUse() + // System.out.println("Name of active Java-Threads: "+thread.getName()+""); - { + // System.out.println("active Java-Thread is Daemon: "+thread.isDaemon();+""); - return engOpenSingleUse(""); + switch (status) { - } + case engOpenI: + epI = engOpenNATIVE(startCmdS); + releaseWaitForValue(); + break; - // ************************** engOpenSingleUse ***************************** + case engOpenSingleUseI: + epI = engOpenSingleUseNATIVE(startCmdS); - /** Open engine for single use. This command is used to open + releaseWaitForValue(); - * multiple connections to matlab. + break; - * + case engCloseI: + retValI = engCloseNATIVE(epI); - *

E.g.:
+ releaseWaitForValue(); - *

+				break;
 
-    *   int a,b;
+			case engEvalStringI:
+				retValI = engEvalStringNATIVE(epI, engEvalStringS);
 
-    *   JMatLink engine = new JMatLink();
+				releaseWaitForValue();
 
-    *   a = engine.engOpenSingleUse("start matlab");   // start first matlab session
+				break;
 
-    *   b = engine.engOpenSingleUse("start matlab");   // start second matlab session
+			case engGetScalarI:
+				engGetScalarD = engGetScalarNATIVE(epI, arrayS);
 
-    *   engine.engEvalString(a, "surf(peaks)");
+				releaseWaitForValue();
 
-    *   engine.engEvalString(b, "foo=ones(10,0)");
+				break;
 
-    *   engine.engClose(a);
+			case engGetVectorI:
+				engGetVectorD = engGetVectorNATIVE(epI, arrayS);
 
-    *   engine.engClose(b);
+				releaseWaitForValue();
 
-    * 
+ break; - ***************************************************************************/ + case engGetArrayI: + engGetArrayD = engGetArrayNATIVE(epI, arrayS); - public synchronized int engOpenSingleUse(String startCmdS) + releaseWaitForValue(); - { + break; - lockEngineLock(); + case engGetCharArrayI: + engGetCharArrayS = engGetCharArrayNATIVE(epI, arrayS); - lockWaitForValue(); + releaseWaitForValue(); + break; + case engPutArray2dI: + engPutArrayNATIVE(epI, arrayS, engPutArray2dD); - this.startCmdS = startCmdS; + releaseWaitForValue(); + break; + case engOutputBufferI: + engOutputBufferS = engOutputBufferNATIVE(epI, buflenI); - callThread( engOpenSingleUseI ); + releaseWaitForValue(); + break; + default: // System.out.println("thread default switch statem."); - WaitForValue(); + } - releaseEngineLock(); + status = 0; + lockThreadB = true; + while (lockThreadB == true) { - return this.epI; + synchronized (this) { - } + try { + wait(); + } // wait until next command is available + catch (InterruptedException e) { + } + } + } + // System.out.println("JMatLink: thread awoke and passed lock"); - // ***************************** engClose ***************************** + if (destroyJMatLinkB == true) + break; - /** Close the connection to matlab. + } // end while - * + if (debugB) + System.out.println("JMatLink: thread terminated"); - *

E.g.:
+ } // end run - *

+	// //////////////////////////////////////////////////////////////////////////////
 
-    *  JMatLink engine = new JMatLink();
+	// The MATLAB engine is served by a thread. Threads don't have methods
 
-    *  engine.engOpen();
+	// which can be called. So we need to send messages to that thread
 
-    *  engine.engEvalString("surf(peaks)");
+	// by using notifyAll. In the meantime NO OTHER methods is allowed to
 
-    *  engine.engClose();
+	// access our thread (engine) so we lock everything up.
 
-    * 
+ private void lockEngineLock() { - ***************************************************************************/ + synchronized (this) { - public synchronized void engClose() + while (lockEngineB == true) { - { + try { // System.out.println("lockEngineLock locked"); - engClose( this.epI ); + wait(); + } // wait until last command is finished - } + catch (InterruptedException e) { + } + } + // now lockEngineB is false + lockEngineB = true; + } - // ***************************** engClose ***************************** + } // end lockEngine - /** Close a specified connection to an instance of matlab. + private synchronized void releaseEngineLock() { - * + lockEngineB = false; - *

E.g.:
+ notifyAll(); - *

+	}
 
-    *  int a,b;
+	// //////////////////////////////////////////////////////////////////////////////
 
-    *  JMatLink engine = new JMatLink();
+	// The MATLAB engine is served by a thread. Threads don't have methods
 
-    *  a = engine.engOpenSingleUse();       // start first  matlab session
+	// which can be called directly. If we send a command that returns data
 
-    *  b = engine.engOpenSingleUse();       // start second matlab session
+	// back to the calling function e.g. engGetArray("array"), we'll notify
 
-    *  engine.engEvalString(b, "surf(peaks)");
+	// the main thread to get the data from matlab. Since the data is collected
 
-    *  engine.engEvalString(a, "array = randn(23)");
+	// in another thread, we don't know exactly when the data is available,
+	// since
 
-    *  engine.engClose(a);      // Close the first  connection to matlab
+	// this is a concurrent situation.
 
-    *  engine.engClose(b);      // Close the second connection to matlab
+	// The solution is simple: I always use a locking-mechanism to wait for the
 
-    * 
+ // data. The main thread will release the lock and the calling method can - ***************************************************************************/ + // return the data. - public synchronized void engClose( int epI) + // - { + // Steps: - // close connection and terminate MATLAB + // 1. a method that returns data calls the locking method - lockEngineLock(); + // 2. notify the thread to call matlab - lockWaitForValue(); + // 3. wait for the returned data + // 4. after the thread itself got the data it releases the locks method + // 5. return data - this.epI = epI; + private synchronized void lockWaitForValue() { + lockWaitForValueB = true; + } - callThread( engCloseI ); + private void WaitForValue() { + synchronized (this) { + while (lockWaitForValueB == true) { - WaitForValue(); + try { // System.out.println("lockWaitForValue locked"); - releaseEngineLock(); + wait(); + } // wait for return value + catch (InterruptedException e) { + } + } - // return retValI; Return value indicates success + } - } + // System.out.println("WaitForValue released"); + } // end waitForValue + private synchronized void releaseWaitForValue() { + lockWaitForValueB = false; + notifyAll(); - // ***************************** engEvalString ***************************** + } - /** Evaluate an expression in matlab's workspace. + // ////////////////////////////////////////////////////////////////////////////// - * + // // Utility methods //// - * E.g.:
+ // Convert an n*n double array to n*1 String vector - *
+	private String[] double2String(double[][] d)
 
-    *   JMatLink engine = new JMatLink();
+	{
 
-    *   engine.engOpen();
+		String encodeS[] = new String[d.length]; // String vector
 
-    *   engine.engEvalString("surf(peaks)");
+		// for all rows
 
-    *   engine.engClose();
+		for (int n = 0; n < d.length; n++) {
 
-    * 
+ byte b[] = new byte[d[n].length]; - ***************************************************************************/ + // convert row from double to byte - public synchronized void engEvalString(String evalS) + for (int i = 0; i < d[n].length; i++) + b[i] = (byte) d[n][i]; - { + // convert byte to String - engEvalString( this.epI, evalS); + try { + encodeS[n] = new String(b, "UTF8"); + } - } + catch (UnsupportedEncodingException e) { + } + } + return encodeS; - - - // ***************************** engEvalString ************************* - - /** Evaluate an expression in a specified workspace. - - * - - *

E.g.:
- - *

-
-    *  int a,b;
-
-    *  JMatLink engine = new JMatLink();
-
-    *  a = engine.engOpenSingleUse();
-
-    *  engine.engEvalString(a, "surf(peaks)");
-
-    *  engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized void engEvalString(int epI, String evalS) - - { - - // evaluate expression "evalS" in specified engine Ep - - if (debugB) System.out.println("eval(ep,String) in " + epI + " "+evalS); - - lockEngineLock(); - - lockWaitForValue(); - - - - this.epI = epI; - - engEvalStringS = evalS; - - - - callThread( engEvalStringI ); - - - - WaitForValue(); - - releaseEngineLock(); - - - - if (debugB) System.out.println("eval(ep,String) out "+epI+" "+evalS); - - // return retValI; Return value indicates success - - } - - - - - - // ***************************** engGetScalar ************************** - - /** Get a scalar value from matlab's workspace. - - * - - *

E.g.:
- - *

-
-    *  double a;
-
-    *  JMatLink engine = new JMatLink();
-
-    *  engine.engOpen();
-
-    *  engine.engEvalString("foo = sin( 3 )");
-
-    *  a = engine.engGetScalarValue("foo");
-
-    *  engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized double engGetScalar(String arrayS) - - { - - return engGetScalar( this.epI, arrayS); - - } - - - - - - // ***************************** engGetScalar ************************** - - /** Get a scalar value from a specified workspace. - - * - - *

E.g.:
- - *

-
-    *   double a;
-
-    *   int b;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   b = engine.engOpenSigleUse();
-
-    *   engine.engEvalString(b, "foo = sin( 3 )");
-
-    *   a = engine.engGetScalarValue(b, "foo");
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized double engGetScalar(int epI, String arrayS) - - { - - // Get scalar value or element (1,1) of an array from - - // MATLAB's workspace - - // Only real values are supported right now - - - - lockEngineLock(); - - lockWaitForValue(); - - - - /* copy parameters to global variables */ - - this.epI = epI; - - this.arrayS = arrayS; - - - - callThread( engGetScalarI ); - - - - - - WaitForValue(); - - releaseEngineLock(); - - - - return engGetScalarD; - - } - - - - - - // ***************************** engGetVector ************************** - - /** Get an array (1 * n) from matlab's workspace. - - * - - *

E.g.:
- - *

-
-    *   double[] array;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engEvalString("array = randn(10,1);");
-
-    *   array = engine.engGetVector("array");
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized double[] engGetVector( String arrayS ) - - { - - return engGetVector( this.epI, arrayS ); - - } - - - - // ***************************** engGetVector ************************** - - /** Get an array (1 * n) from a specified workspace. - - * - - *

E.g.:
- - *

-
-    *   int b;
-
-    *   double[] array;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   b = engine.engOpenSingleUse();
-
-    *   engine.engEvalString(b, "array = randn(10,1);");
-
-    *   array = engine.engGetVector(b, "array");
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized double[] engGetVector( int epI, String arrayS ) - - { - - // only real values are supported so far - - lockEngineLock(); - - lockWaitForValue(); - - - - this.epI = epI; - - this.arrayS = arrayS; - - - - callThread( engGetVectorI ); - - - - WaitForValue(); - - releaseEngineLock(); - - - - return engGetVectorD; - - } - - - - - - // ***************************** engGetArray *************************** - - /** Get an array from matlab's workspace. - - * - - *

E.g.:
- - *

-
-    *   int b;
-
-    *   double[][] array;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engEvalString("array = randn(10);");
-
-    *   array = engine.engGetArray("array");
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized double[][] engGetArray( String arrayS ) - - { - - return engGetArray( this.epI, arrayS ); - - } - - - - - - // ***************************** engGetArray *************************** - - /** Get an array from a specified instance/workspace of matlab. - - * - - *

E.g.:
- - *

-
-    *   int b;
-
-    *   double[][] array;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   b = engine.engOpenSingleUse();
-
-    *   engine.engEvalString(b, "array = randn(10);");
-
-    *   array = engine.engGetArray(b, "array");
-
-    *   engine.engClose(b);
-
-    * 
- - ***************************************************************************/ - - public synchronized double[][] engGetArray( int epI, String arrayS ) - - { - - // only real values are supported so far - - lockEngineLock(); - - lockWaitForValue(); - - - - this.epI = epI; - - this.arrayS = arrayS; - - - - callThread( engGetArrayI ); - - WaitForValue(); - - releaseEngineLock(); - - - - return engGetArrayD; - - } - - - - // ************************** engGetCharArray ***************************** - - /** Get an 'char' array (string) from matlab's workspace. - - * - - *

E.g.:
- - *

-
-    *   String array;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engEvalString("array = 'hello world';");
-
-    *   array = engine.engCharArray("array");
-
-    *   System.out.println("output = "+ array);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized String[] engGetCharArray(String arrayS) - - { - - // convert to double array - - engEvalString( "engGetCharArrayD=double(" + arrayS +")" ); - - - - // get double array - - double[][] arrayD = engGetArray("engGetCharArrayD"); - - - - // delete temporary double array - - engEvalString("clear engGetCharArrayD"); - - - - // convert double back to char - - return double2String( arrayD ); - - } - - - - - - // ***************************** engPutArray *************************** - - /** Put an array into a specified workspace. - - * - - *

E.g.:
- - *

-
-    *   int array = 1;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engPutArray("array", array);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized void engPutArray( String arrayS, int valueI ) - - { - - engPutArray( this.epI, arrayS, new Integer(valueI).doubleValue()); - - } - - - - - - // ***************************** engPutArray *************************** - - // public synchronized void engPutArray( String arrayS, int[] valuesI ) - - // { - - // engPutArray( this.epI, arrayS, (double[])valuesI ); - - // } - - - - - - // ***************************** engPutArray *************************** - - /** Put an array into matlab's workspace. - - * - - *

E.g.:
- - *

-
-    *   double array = 1;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engPutArray("array", array);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized void engPutArray( String arrayS, double valueD ) - - { - - engPutArray( this.epI, arrayS, valueD); - - } - - - - - - // ***************************** engPutArray ***************************** - - /** Put an array into a specified instance/workspace of matlab. - - * - - *

E.g.:
- - *

-
-    *   int b;
-
-    *   double array = 1;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   b = engine.engOpenSingleUse();
-
-    *   engine.engPutArray(b, "array", array);
-
-    *   engine.engClose(b);
-
-    * 
- - ***************************************************************************/ - - public synchronized void engPutArray( int epI, String arrayS, double valueD ) - - { - - - - double vDD[][] = {{0.0}}; - - vDD[0][0] = valueD; - - engPutArray( epI, arrayS, vDD ); // nxn dimensional - - } - - - - - - // ***************************** engPutArray *************************** - - /** Put an array (1 dimensional) into a specified instance/workspace of - - * matlab. - - * - - *

E.g.:
- - *

-
-    *   double[] array = {1.0 , 2.0 , 3.0};
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engPutArray("array", array);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized void engPutArray( String arrayS, double[] valuesD ) - - { - - engPutArray( this.epI, arrayS, valuesD ); - - } - - - - - - // ***************************** engPutArray ***************************** - - /** Put an array (1 dimensional) into a specified instance/workspace of - - * matlab. - - * - - *

E.g.:
- - *

-
-    *   int b;
-
-    *   double[] array = {1.0 , 2.0 , 3.0};
-
-    *   JMatLink engine = new JMatLink();
-
-    *   b = engine.engOpenSingleUse();
-
-    *   engine.engPutArray(b, "array", array);
-
-    *   engine.engClose(b);
-
-    * 
- - ***************************************************************************/ - - public synchronized void engPutArray(int epI, String arrayS, double[] valuesD) - - { - - double[][] vDD = new double[1][valuesD.length]; // 1xn array - - - - if (debugB) System.out.println("length = "+valuesD.length); - - - - vDD[0] = valuesD; // copy row - - - - engPutArray( epI, arrayS, vDD ); - - } - - - - - - // ***************************** engPutArray *************************** - - /** Put an array (2 dimensional) into matlab's workspace. - - * - - *

E.g.:
- - *

-
-    *   double[][] array={{1.0 , 2.0 , 3.0},
-
-    *                     {4.0 , 5.0 , 6.0}};
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpenSingleUse();
-
-    *   engine.engPutArray("array", array);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized void engPutArray( String arrayS, double[][] valuesDD ) - - { - - engPutArray( this.epI, arrayS, valuesDD ); - - } - - - - - - // ***************************** engPutArray *************************** - - /** Put an array (2 dimensional) into a specified instance/workspace of - - * matlab. - - * - - *

E.g.:
- - *

-
-    *   int b;
-
-    *   double[][] array={{1.0 , 2.0 , 3.0},
-
-    *                     {4.0 , 5.0 , 6.0}};
-
-    *   JMatLink engine = new JMatLink();
-
-    *   b = engine.engOpenSingleUse();
-
-    *   engine.engPutArray(b, "array", array);
-
-    *   engine.engClose(b);
-
-    * 
- - ***************************************************************************/ - - public synchronized void engPutArray(int epI, String arrayS, double[][] valuesDD) - - { - - // send an array to MATLAB - - // only real values are supported so far - - lockEngineLock(); - - lockWaitForValue(); - - - - this.epI = epI; - - this.arrayS = arrayS; - - this.engPutArray2dD = valuesDD; - - - - callThread( engPutArray2dI ); - - - - WaitForValue(); - - releaseEngineLock(); - - } - - - - - - // ***************************** engOutputBuffer *********************** - - /** Return the outputs of previous commands from matlab's workspace. - - * - - *

E.g.:
- - *

-
-    *   String buffer;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engEvalString("surf(peaks)");
-
-    *   buffer = engine.engOutputBuffer();
-
-    *   System.out.println("workspace " + buffer);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized String engOutputBuffer( ) - - { - - return engOutputBuffer( this.epI, this.buflenI ); - - } - - - - // ***************************** engOutputBuffer *********************** - - /** Return the outputs of previous commands from a specified instance/ - - * workspace form matlab. - - * - - *

E.g.:
- - *

-
-    *   String buffer;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engEvalString("surf(peaks)");
-
-    *   buffer = engine.engOutputBuffer();
-
-    *   System.out.println("workspace " + buffer);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized String engOutputBuffer( int epI ) - - { - - return engOutputBuffer( epI, this.buflenI ); - - } - - - - // ***************************** engOutputBuffer *********************** - - /** Return the ouputs of previous commands in matlab's workspace. - - * - - * Right now the parameter buflen is not supported. - - * - - *

E.g.:
- - *

-
-    *   String buffer;
-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpen();
-
-    *   engine.engEvalString("surf(peaks)");
-
-    *   buffer = engine.engOutputBuffer();
-
-    *   System.out.println("workspace " + buffer);
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public synchronized String engOutputBuffer( int epI, int buflenI ) - - { - - // get the output buffer from MATLAB - - if (debugB) System.out.println("Thread in: "+Thread.currentThread().getName()); - - - - lockEngineLock(); - - lockWaitForValue(); - - - - this.epI = epI; - - this.buflenI = buflenI; - - - - callThread( engOutputBufferI ); - - - - WaitForValue(); - - releaseEngineLock(); - - if (debugB) System.out.println("Thread out: "+Thread.currentThread().getName()); - - - - return engOutputBufferS; - - } - - - - - - // ***************************** setDebug ******************************* - - /* Switch on or disable debug information printed to standard output. - - * - - *

Default setting is debug info disabled. - - *

E.g.:
- - *

-
-    *   JMatLink engine = new JMatLink();
-
-    *   engine.engOpenSingleUse();
-
-    *   engine.setDebug(true);
-
-    *   engine.engEvalString("a=ones(10,5);");
-
-    *   engine.engClose();
-
-    * 
- - ***************************************************************************/ - - public void setDebug( boolean debugB ) - - { - - this.debugB = debugB; - - setDebugNATIVE( debugB ); - - } - - - - - - //////////////////////////////////////////////////////////////////////////////// - - // This method notifys the main thread to call matlab's engine - - // Since threads don't have methods, we set a variable which - - // contains the necessary information about what to do. - - private synchronized void callThread(int status) - - { - - this.status = status; - - lockThreadB = false; - - notifyAll(); - - } - - - - - -//////////////////////////////////////////////////////////////////////////////// - -// The run methods does ALL calls to the native methods - -// The keyword "synchronized" is neccessary to block the run() - -// method as long as one command needs to get executed. - -public synchronized void run() - -{ - - int tempRetVal; - - - - if (debugB) System.out.println("JMatLink: thread is running"); - - while (true) { - - // System.out.println("Number of Java-Threads: "+Thread.activeCount()+""); - - // Thread thread = Thread.currentThread(); - - // System.out.println("Name of active Java-Threads: "+thread.getName()+""); - - // System.out.println("active Java-Thread is Daemon: "+thread.isDaemon();+""); - - - - - - switch (status) { - - case engOpenI: epI = engOpenNATIVE( startCmdS ); - - releaseWaitForValue(); - - break; - - - - case engOpenSingleUseI: epI = engOpenSingleUseNATIVE( startCmdS ); - - releaseWaitForValue(); - - break; - - - - case engCloseI: retValI = engCloseNATIVE( epI ); - - releaseWaitForValue(); - - break; - - - - case engEvalStringI: retValI = engEvalStringNATIVE(epI, engEvalStringS); - - releaseWaitForValue(); - - break; - - - - case engGetScalarI: engGetScalarD = engGetScalarNATIVE(epI, arrayS ); - - releaseWaitForValue(); - - break; - - - - case engGetVectorI: engGetVectorD = engGetVectorNATIVE(epI, arrayS ); - - releaseWaitForValue(); - - break; - - - - case engGetArrayI: engGetArrayD = engGetArrayNATIVE(epI, arrayS ); - - releaseWaitForValue(); - - break; - - - - case engGetCharArrayI: engGetCharArrayS = engGetCharArrayNATIVE(epI, arrayS ); - - releaseWaitForValue(); - - break; - - - - case engPutArray2dI: engPutArrayNATIVE( epI, arrayS, engPutArray2dD ); - - releaseWaitForValue(); - - break; - - - - case engOutputBufferI: engOutputBufferS = engOutputBufferNATIVE( epI, buflenI ); - - releaseWaitForValue(); - - break; - - - - - - default: //System.out.println("thread default switch statem."); - - } - - status=0; - - - - lockThreadB = true; - - while (lockThreadB == true) { - - synchronized(this) { - - try { wait();} // wait until next command is available - - catch (InterruptedException e) { } - - } - - } - - //System.out.println("JMatLink: thread awoke and passed lock"); - - if (destroyJMatLinkB == true) break; - - } // end while - - if (debugB) System.out.println("JMatLink: thread terminated"); - -} // end run - - - - - -//////////////////////////////////////////////////////////////////////////////// - -// The MATLAB engine is served by a thread. Threads don't have methods - -// which can be called. So we need to send messages to that thread - -// by using notifyAll. In the meantime NO OTHER methods is allowed to - -// access our thread (engine) so we lock everything up. - - private void lockEngineLock(){ - - synchronized(this){ - - while (lockEngineB==true){ - - try { //System.out.println("lockEngineLock locked"); - - wait();} // wait until last command is finished - - catch (InterruptedException e) { } - - } - - //now lockEngineB is false - - lockEngineB = true; - - } - - } // end lockEngine - - - - private synchronized void releaseEngineLock(){ - - lockEngineB = false; - - notifyAll(); - - } - - - -//////////////////////////////////////////////////////////////////////////////// - -// The MATLAB engine is served by a thread. Threads don't have methods - -// which can be called directly. If we send a command that returns data - -// back to the calling function e.g. engGetArray("array"), we'll notify - -// the main thread to get the data from matlab. Since the data is collected - -// in another thread, we don't know exactly when the data is available, since - -// this is a concurrent situation. - -// The solution is simple: I always use a locking-mechanism to wait for the - -// data. The main thread will release the lock and the calling method can - -// return the data. - -// - -// Steps: - -// 1. a method that returns data calls the locking method - -// 2. notify the thread to call matlab - -// 3. wait for the returned data - -// 4. after the thread itself got the data it releases the locks method - -// 5. return data - - - - private synchronized void lockWaitForValue(){ - - lockWaitForValueB = true; - - } - - - - private void WaitForValue(){ - - synchronized(this){ - - while (lockWaitForValueB==true){ - - try { //System.out.println("lockWaitForValue locked"); - - wait();} // wait for return value - - catch (InterruptedException e) { } - - } - - } - - //System.out.println("WaitForValue released"); - - } // end waitForValue - - - - private synchronized void releaseWaitForValue(){ - - lockWaitForValueB = false; - - notifyAll(); - - } - - - - - -//////////////////////////////////////////////////////////////////////////////// - -//// Utility methods //// - - - - - - // Convert an n*n double array to n*1 String vector - - private String[] double2String(double[][] d) - - { - - String encodeS[]=new String[d.length]; // String vector - - - - // for all rows - - for (int n=0; n