Hi Leute,
in dem Thread http://www.java-forum.org/allgemeine-java-themen/102689-jni-problem.html wollteich im Helloworld-kontext eine dll über JNI in Java aufrufen und habe es mit Hilfe geschaft.
Mei Ziel ist es nun eine Schnittstelle zu Matlab zu bauen und hierfür möchte ich folgende C datei zu einer dll kompilieren:
Diese Vorlage habe ich von Mathworks! Die entsprechende Header Datei habe ich aus der Java Datei erstellt:
Ich hab mal extra die Kommentare drin gelassen! Diese Java Vorlagen wurden soweit ich es entnehmen konnte für Linux erstellt. Ich jedoch benutze Windows. Meine Main Methode sieht wie folgt aus:
Nun habe ich über VS2010 die C datei kompiliert, doch bekomme ich unter Java die abgefangene Nachricht beim öffnen von Matlab:
Da diese Vorlage schon häufig benuzt wurd bin ich der meinung das der Code an sich in Ordnung ist und das bei der kompilierung etwas falsch sein muss.
Da ich bei der kompilierung auch einige DLL includen muss frage ich mich, ob man dies bei MingW auch nun über -I machen kann. Leider klappte die kompilierung über MingW bisher nicht und ich weiß nicht ob ich VS2010 trauen kann!
Würde mich über jede Hilfe freuen!
in dem Thread http://www.java-forum.org/allgemeine-java-themen/102689-jni-problem.html wollteich im Helloworld-kontext eine dll über JNI in Java aufrufen und habe es mit Hilfe geschaft.
Mei Ziel ist es nun eine Schnittstelle zu Matlab zu bauen und hierfür möchte ich folgende C datei zu einer dll kompilieren:
Code:
#include <jni.h>
#include "MatlabNativeInterface_Engine.h"
#include <stdio.h>
#include "engine.h"
#define DEFAULT_BUFFERSIZE 65536
Engine* ep;
char outputBuffer[DEFAULT_BUFFERSIZE];
JNIEXPORT void JNICALL
Java_MatlabNativeInterface_Engine_open(JNIEnv *env, jobject obj, const jstring startcmd) {
const char *c_string = (*env)->GetStringUTFChars(env, startcmd, 0);
if (!(ep = engOpen(c_string))) {
if (ep == NULL ) {
jclass exception;
(*env)->ReleaseStringUTFChars(env, startcmd, c_string);
exception = (*env)->FindClass(env, "java/io/IOException");
if (exception == 0) return;
(*env)->ThrowNew(env, exception, "Opening Matlab failed.");
return;
}
(*env)->ReleaseStringUTFChars(env, startcmd, c_string);
/* indicate that output should not be discarded but stored in */
/* outputBuffer */
engOutputBuffer(ep, outputBuffer, DEFAULT_BUFFERSIZE);
}
JNIEXPORT void JNICALL
Java_MatlabNativeInterface_Engine_close(JNIEnv *env, jobject obj) {
engClose(ep);
if (engClose(ep) == 1) {
jclass exception;
exception = (*env)->FindClass(env, "java/io/IOException");
if (exception == 0) return;
(*env)->ThrowNew(env, exception, "Closing Matlab failed.");
return;
}
}
JNIEXPORT void JNICALL
Java_MatlabNativeInterface_Engine_evalString(JNIEnv *env, jobject obj, const jstring j_string) {
const char *c_string;
engEvalString(ep, c_string);
c_string = (*env)->GetStringUTFChars(env, j_string, 0);
if (engEvalString(ep, c_string) != 0) {
jclass exception;
exception = (*env)->FindClass(env, "java/io/IOException");
if (exception == 0) return;
(*env)->ThrowNew(env, exception, "Error while sending/receiving data.");
}
(*env)->ReleaseStringUTFChars(env, j_string, c_string);
}
JNIEXPORT jstring JNICALL
Java_MatlabNativeInterface_Engine_getOutputString(JNIEnv *env, jobject obj, jint numberOfChars) {
char *c_string;
jstring j_string;
if (numberOfChars > DEFAULT_BUFFERSIZE) {
numberOfChars = DEFAULT_BUFFERSIZE;
}
c_string = (char *) malloc ( sizeof(char)*(numberOfChars+1) );
c_string[numberOfChars] = 0;
strncpy(c_string, outputBuffer, numberOfChars);
j_string = (*env)->NewStringUTF(env, c_string);
free(c_string);
return j_string;
}
Diese Vorlage habe ich von Mathworks! Die entsprechende Header Datei habe ich aus der Java Datei erstellt:
Java:
package MatlabNativeInterface;
import java.io.*;
/**
* <b>Java Engine for Matlab via Java Native Interface (JNI)</b><br>
* This class demonstrates how to call Matlab from a Java program via
* JNI, thereby employing Matlab as the computation engine.
* The Matlab engine operates by running in the background as a separate
* process from your own program.
* <p>
* Date: 04.04.03
* <p>
* Copyright (c) 2003 Andreas Klimke, Universit�t Stuttgart
* <p>
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* <p>
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* @author W. Andreas Klimke, University of Stuttgart
* (klimke@ians.uni-stuttgart.de)
* @version 0.1
*
*/
public class Engine {
/**
* Calls the function <code>engOpen</code> of Matlab's C Engine library.
* Excerpts from the Matlab documentation:
* "On UNIX systems, if startcmd is NULL or the empty string,
* <code>engOpen</code> starts MATLAB on the current host using the
* command <code>matlab</code>. If startcmd is a hostname, <code>engOpen
* </code> starts MATLAB on the designated host by embedding the specified
* hostname string into the larger string:
* <code>rsh hostname \"/bin/csh -c 'setenv DISPLAY\ hostname:0; matlab'\"
* </code>. If startcmd is any other string (has white space in it, or
* nonalphanumeric characters), the string is executed literally to start
* MATLAB. On Windows, the startcmd string must be NULL."<br>
* See the Matlab documentation, chapter "External Interfaces/API
* Reference/C Engine Functions" for further information.
* @param startcmd The start command string.
* @throws IOException Thrown if starting the process was not successful.
*/
public native void open(String startcmd) throws IOException;
/**
* Calls the function <code>engClose</code> of Matlab's C Engine
* library. This routine allows you to quit a MATLAB engine session.
* @throws IOException Thrown if Matlab could not be closed.
*/
public native void close() throws IOException;
/**
* Calls the function <code>engEvalString</code> of Matlab's C Engine
* library. Evaluates the expression contained in string for the MATLAB
* engine session previously started by <code>open</code>.
* See the Matlab documentation, chapter "External Interfaces/API
* Reference/C Engine Functions" for further information.
* @param str Expression to be evaluated.
* @throws IOException Thrown if data could not be sent to Matlab. This
* may happen if Matlab is no longer running.
* @see #open
*/
public native void evalString(String str) throws IOException;
/**
* Reads a maximum of <code>numberOfChars</code> characters from
* the Matlab output buffer and returns the result as String.<br>
* If the number of available characters exceeds <code>numberOfChars</code>,
* the additional data is discarded. The Matlab process must be opended
* previously with <code>open()</code>.<br>
* @return String containing the Matlab output.
* @see #open
* @throws IOException Thrown if data could not be received. This may
* happen if Matlab is no longer running.
*/
public native String getOutputString(int numberOfChars);
/**
* Initialize the native shared library.
*/
static {
System.loadLibrary("EngineDll_St");
System.err.println("Native Matlab shared library loaded.");
}
}
Ich hab mal extra die Kommentare drin gelassen! Diese Java Vorlagen wurden soweit ich es entnehmen konnte für Linux erstellt. Ich jedoch benutze Windows. Meine Main Methode sieht wie folgt aus:
Java:
package main;
import MatlabNativeInterface.*;
import java.io.*;
/**
* Demonstration program for connecting Java with Matlab using the Java
* Native Interface (JNI). Wrapper functions access Matlab via Matlab's
* native C Engine library.
**/
public class Main {
public static void main(String[] args) {
Engine engine = new MatlabNativeInterface.Engine();
try {
// Matlab start command:
engine.open("matlab -nosplash -nojvm");
// Display output:
System.out.println(engine.getOutputString(500));
// Example: Solve the system of linear equations Ax = f with
// Matlab's Preconditioned Conjugate Gradients method.
engine.evalString("A = gallery('lehmer',10);"); // Define Matrix A
engine.evalString("f = ones(10,1);"); // Define vector f
engine.evalString("pcg(A,f,1e-5)"); // Compute x
// Retrieve output:
System.out.println(engine.getOutputString(500));
// Close the Matlab session:
engine.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Nun habe ich über VS2010 die C datei kompiliert, doch bekomme ich unter Java die abgefangene Nachricht beim öffnen von Matlab:
Native Matlab shared library loaded.
java.io.IOException: Opening Matlab failed.
at MatlabNativeInterface.Engine.open(Native Method)
at main.Main.main(Main.java:16)
Da diese Vorlage schon häufig benuzt wurd bin ich der meinung das der Code an sich in Ordnung ist und das bei der kompilierung etwas falsch sein muss.
Da ich bei der kompilierung auch einige DLL includen muss frage ich mich, ob man dies bei MingW auch nun über -I machen kann. Leider klappte die kompilierung über MingW bisher nicht und ich weiß nicht ob ich VS2010 trauen kann!
Würde mich über jede Hilfe freuen!