|
From: | David Bateman |
Subject: | [Changeset] Re: [OctDev] Java calling Octave via JNI |
Date: | Fri, 05 Sep 2008 10:41:07 +0200 |
User-agent: | Thunderbird 2.0.0.16 (X11/20080725) |
David Bateman wrote:
Seeing as how this question has come up a number of times, I suggest the attached changeset that adds an example of how to initialize the interpreter and use it from a standalone application.MartinHepperle wrote:eval_string can only work if the interpreter is initialized.. Check the mailing lists for how to initialize the interpreter.Hello all, again this nasty Java -> Octave connection.I also want to embed Octave into a Java program and call Octave functionsfrom Java. Initially I started with programming an execution engine which starts octave.exe and connected to its standard input and output pipes. Thisconcept works (in the meantime I also found two solutions which implement the same technique) but is somewhat ugly and inefficient due to conversionsto and from stringsWhat I tried now was to call the Octave DLLs (Windows platform) directly viaa C wrapper and using JNI.This technique provides a very elegant solution and I have used this in thepast to call C and FORTRAN codes from Java. I want to define some globalvariables, set the values from Java, execute some user supplied functionsand finally return the results (global variables set inside the user functions) to Java. Now with the Octrave DLLs I stumbled across a problem.To study the interface to ther DLLs I started with a C++ program. Basically I used the following logic://----------------------------- // start and initialize Octave (once, then keep it alive)char * pArgs[] = {"octave.exe","--path", "C:\\Programme\\Octave", "--norc",NULL}; int iRet = octave_main (4 pArgs, true); //----------------------------- // execute some commands std::string s = std::string("global Output;\nglobal Input;\nInput=12;\nOutput=2*Input;\n"); octave_value x = eval_string (s, false, parse_status);// examine the returned "x" with x.isnumeric() etc. works when code is in anexecutable (.exe) file// what does the follwing code do? It works, but where is the variable inOctave? set_global_value (std::string(cName), val); octave_value vReturn = get_global_value (std::string(cName)); // the variable has the correct value, but is_globally_visible (std::string(Name)) returns false... // what does global mean here? // terminate Octave do_octave_atexit(); //-----------------------------All this works well when I have the code inside an executable C++ program(MSVC8.0). So far so good.Now for the interface via JNI I have to put this into a DLL which provides athin layer between Java objects and the C interface to Octave. If I put the same code inside a DLL I can initialize Octave, but theeval_string () and other functions doe not work - they seem to do nothing. I found can do somethings with set_global_value () and get_global_value (), but this is not enough and also these "global" values seem to be somethingelse than global variables in Octave. Anyway, I see that eval_string() seems to work when called from a Cexecutable, but not when I call it from a DLL. Could this have something todo with i/o streams which are different in a DLL and in an EXE? Any ideas where to look and how to test? Thank You, MartinD.
Regards David -- David Bateman address@hiddenMotorola Labs - Paris +33 1 69 35 48 04 (Ph) Parc Les Algorithmes, Commune de St Aubin +33 6 72 01 06 33 (Mob) 91193 Gif-Sur-Yvette FRANCE +33 1 69 35 77 01 (Fax) The information contained in this communication has been classified as: [x] General Business Information [ ] Motorola Internal Use Only [ ] Motorola Confidential Proprietary
# HG changeset patch # User David Bateman <address@hidden> # Date 1220603756 -7200 # Node ID 2ea73884a0043cee526dc0651bdee03f217e7f30 # Parent 686fedc6a026f0aaafbfe95c53a362060af94d7f Add explanationation of initializing the interpreter in a standalone program diff --git a/doc/interpreter/dynamic.txi b/doc/interpreter/dynamic.txi --- a/doc/interpreter/dynamic.txi +++ b/doc/interpreter/dynamic.txi @@ -1621,28 +1621,7 @@ following C++ program, uses class Matrix following C++ program, uses class Matrix from liboctave.a or liboctave.so. address@hidden address@hidden -#include <iostream> -#include <octave/oct.h> -int -main (void) address@hidden - std::cout << "Hello Octave world!\n"; - int n = 2; - Matrix a_matrix = Matrix (n, n); - for (octave_idx_type i = 0; i < n; i++) - @{ - for (octave_idx_type j = 0; j < n; j++) - @{ - a_matrix (i, j) = (i + 1) * 10 + (j + 1); - @} - @} - std::cout << a_matrix; - return 0; address@hidden address@hidden group address@hidden example address@hidden @noindent mkoctfile can then be used to build a standalone application with a @@ -1650,8 +1629,8 @@ command like @example @group -$ mkoctfile --link-stand-alone hello.cc -o hello -$ ./hello +$ mkoctfile --link-stand-alone standalone.cc -o standalone +$ ./standalone Hello Octave world! 11 12 21 22 @@ -1660,4 +1639,24 @@ Hello Octave world! @end example Note that the application @code{hello} will be dynamically linked -against the octave libraries and any octave support libraries. +against the octave libraries and any octave support libraries. The above +allows the Octave math libraries to be used by an application. It does +not however allow the script files, oct-files or builtin functions of +Octave to be used by the application. To do that the Octave interpreter +needs to be initialized first. An example of how to do this can then be +seen in the code + address@hidden + address@hidden +which is compiled and run as before as a standalone application with + address@hidden address@hidden +$ mkoctfile --link-stand-alone embedded.cc -o embedded +$ ./embedded +GCD of [10, 15] is 5 +$ address@hidden group address@hidden example + diff --git a/examples/Makefile.in b/examples/Makefile.in --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -39,6 +39,7 @@ SOURCES = \ SOURCES = \ addtwomatrices.cc \ celldemo.cc \ + embedded.cc \ firstmexdemo.c \ fortdemo.cc \ fortsub.f \ @@ -62,6 +63,7 @@ SOURCES = \ oregonator.cc \ oregonator.m \ paramdemo.cc \ + standalone.cc \ stringdemo.cc \ structdemo.cc \ unwinddemo.cc diff --git a/examples/embedded.cc b/examples/embedded.cc new file mode 100644 --- /dev/null +++ b/examples/embedded.cc @@ -0,0 +1,43 @@ +#include <iostream> +#include <octave/oct.h> +#include <octave/octave.h> +#include <octave/parse.h> +int +main (void) +{ + string_vector argv (2); + argv(0) = "embedded"; + argv(1) = "-q"; + + octave_main (2, argv.c_str_vec(), 1); + + octave_idx_type n = 2; + Matrix a_matrix = Matrix (1, 2); + + std::cout << "GCD of ["; + for (octave_idx_type i = 0; i < n; i++) + { + a_matrix (i) = 5 * (i + 1); + if (i != 0) + std::cout << ", " << 5 * (i + 2); + else + std::cout << 5 * (i + 2); + } + std::cout << "] is "; + + octave_value_list in = octave_value (a_matrix); + octave_value_list out = feval ("gcd", in, 1); + + if (!error_state && out.length () > 0) + { + a_matrix = out(0).matrix_value (); + if (a_matrix.numel () == 1) + std::cout << a_matrix(0) << "\n"; + else + std::cout << "invalid\n"; + } + else + std::cout << "invalid\n"; + + return 0; +} diff --git a/examples/standalone.cc b/examples/standalone.cc new file mode 100644 --- /dev/null +++ b/examples/standalone.cc @@ -0,0 +1,18 @@ +#include <iostream> +#include <octave/oct.h> +int +main (void) +{ + std::cout << "Hello Octave world!\n"; + int n = 2; + Matrix a_matrix = Matrix (n, n); + for (octave_idx_type i = 0; i < n; i++) + { + for (octave_idx_type j = 0; j < n; j++) + { + a_matrix (i, j) = (i + 1) * 10 + (j + 1); + } + } + std::cout << a_matrix; + return 0; +}
[Prev in Thread] | Current Thread | [Next in Thread] |