[Changeset] Re: [OctDev] Java calling Octave via JNI

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[Changeset] Re: [OctDev] Java calling Octave via JNI

David Bateman-3
David Bateman wrote:

> MartinHepperle wrote:
>> Hello all,
>>
>> again this nasty Java -> Octave connection.
>>
>> I also want to embed Octave into a Java program and call Octave
>> functions
>> from Java.
>>
>> Initially I started with programming an execution engine which starts
>> octave.exe and connected to its standard input and output pipes. This
>> concept works (in the meantime I also found two solutions which
>> implement
>> the same technique) but is somewhat ugly and inefficient due to
>> conversions
>> to and from strings
>>
>> What I tried now was to call the Octave DLLs (Windows platform)
>> directly via
>> a C wrapper and using JNI.
>> This technique provides a very elegant solution and I have used this
>> in the
>> past to call C and FORTRAN codes from Java. I want to define some global
>> variables, set the values from Java, execute some user supplied
>> functions
>> and 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 an
>> executable (.exe) file
>>
>> // what does the follwing code do? It works, but where is the
>> variable in
>> Octave?
>> 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 a
>> thin layer between Java objects and the C interface to Octave.
>> If I put the same code inside a DLL I can initialize Octave, but the
>> eval_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
>> something
>> else than global variables in Octave.
>>
>> Anyway, I see that eval_string() seems to work when called from a C
>> executable, but not when I call it from a DLL. Could this have
>> something to
>> do 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,
>>
>> Martin
>>
>>
>>
>>
>>  
> eval_string can only work if the interpreter is initialized.. Check
> the mailing lists for how to initialize the interpreter.
>
> D.
>
>
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.

Regards
David


--
David Bateman                                [hidden email]
Motorola 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 <[hidden email]>
# 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.
 
-@example
-@group
-#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;
-@}
-@end group
-@end example
+@examplefile{standalone.cc}
 
 @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
+
+@examplefile{embedded.cc}
+
+@noindent
+which is compiled and run as before as a standalone application with
+
+@example
+@group
+$ mkoctfile --link-stand-alone embedded.cc -o embedded
+$ ./embedded
+GCD of [10, 15] is 5
+$
+@end group
+@end 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;
+}
Reply | Threaded
Open this post in threaded view
|

[Changeset] Re: [OctDev] Java calling Octave via JNI

John W. Eaton-6
On  5-Sep-2008, David Bateman wrote:

| David Bateman wrote:
| > MartinHepperle wrote:
| >> Hello all,
| >>
| >> again this nasty Java -> Octave connection.
| >>
| >> I also want to embed Octave into a Java program and call Octave
| >> functions
| >> from Java.
| >>
| >> Initially I started with programming an execution engine which starts
| >> octave.exe and connected to its standard input and output pipes. This
| >> concept works (in the meantime I also found two solutions which
| >> implement
| >> the same technique) but is somewhat ugly and inefficient due to
| >> conversions
| >> to and from strings
| >>
| >> What I tried now was to call the Octave DLLs (Windows platform)
| >> directly via
| >> a C wrapper and using JNI.
| >> This technique provides a very elegant solution and I have used this
| >> in the
| >> past to call C and FORTRAN codes from Java. I want to define some global
| >> variables, set the values from Java, execute some user supplied
| >> functions
| >> and 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 an
| >> executable (.exe) file
| >>
| >> // what does the follwing code do? It works, but where is the
| >> variable in
| >> Octave?
| >> 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 a
| >> thin layer between Java objects and the C interface to Octave.
| >> If I put the same code inside a DLL I can initialize Octave, but the
| >> eval_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
| >> something
| >> else than global variables in Octave.
| >>
| >> Anyway, I see that eval_string() seems to work when called from a C
| >> executable, but not when I call it from a DLL. Could this have
| >> something to
| >> do 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,
| >>
| >> Martin
| >>
| >>
| >>
| >>
| >>  
| > eval_string can only work if the interpreter is initialized.. Check
| > the mailing lists for how to initialize the interpreter.
| >
| > D.
| >
| >
| 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.

I applied it.

Thanks,

jwe
Reply | Threaded
Open this post in threaded view
|

Re: [OctDev] [Changeset] Re: Java calling Octave via JNI

Jaroslav Hajek-2
On Tue, Sep 9, 2008 at 7:44 PM, John W. Eaton <[hidden email]> wrote:

> On  5-Sep-2008, David Bateman wrote:
>
> | David Bateman wrote:
> | > MartinHepperle wrote:
> | >> Hello all,
> | >>
> | >> again this nasty Java -> Octave connection.
> | >>
> | >> I also want to embed Octave into a Java program and call Octave
> | >> functions
> | >> from Java.
> | >>
> | >> Initially I started with programming an execution engine which starts
> | >> octave.exe and connected to its standard input and output pipes. This
> | >> concept works (in the meantime I also found two solutions which
> | >> implement
> | >> the same technique) but is somewhat ugly and inefficient due to
> | >> conversions
> | >> to and from strings
> | >>
> | >> What I tried now was to call the Octave DLLs (Windows platform)
> | >> directly via
> | >> a C wrapper and using JNI.
> | >> This technique provides a very elegant solution and I have used this
> | >> in the
> | >> past to call C and FORTRAN codes from Java. I want to define some global
> | >> variables, set the values from Java, execute some user supplied
> | >> functions
> | >> and 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 an
> | >> executable (.exe) file
> | >>
> | >> // what does the follwing code do? It works, but where is the
> | >> variable in
> | >> Octave?
> | >> 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 a
> | >> thin layer between Java objects and the C interface to Octave.
> | >> If I put the same code inside a DLL I can initialize Octave, but the
> | >> eval_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
> | >> something
> | >> else than global variables in Octave.
> | >>
> | >> Anyway, I see that eval_string() seems to work when called from a C
> | >> executable, but not when I call it from a DLL. Could this have
> | >> something to
> | >> do 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,
> | >>
> | >> Martin
> | >>
> | >>
> | >>
> | >>
> | >>
> | > eval_string can only work if the interpreter is initialized.. Check
> | > the mailing lists for how to initialize the interpreter.
> | >
> | > D.
> | >
> | >
> | 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.
>
> I applied it.
>

I transplanted this "explanationation" (hg description :-) patch to 3.0.x series




--
RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz
Reply | Threaded
Open this post in threaded view
|

RE: [OctDev] [Changeset] Re: Java calling Octave via JNI

Martin.Hepperle
Hello all,

after some further experimentation I have given up this route.
I guess that there is some version conflict between C++ runtime
DLLs which I could not resolve.  My DLL was able to load the
octave DLLs, but when Octave tried to load its .oct libraries,
which seem to be DLLs under Windows, it was unable to load
them with LoadLibrary() ("cannot find library..., but the
complete path is given, correct and the .oct library is there).
I was using VS 2005 for my C-Java interface DLL which should be
compatible with the Octave DLLS, but it may be that there is a
conflict with differenr runtime libraries.
I did not want to recompile the whole Octave system.

So I switched to the less elegant but workable way of running
octave.exe and connecting to its stdin and stdout streams.
For this I have replaced my test implementation with the basic
but well structured solution from the packages dk.ange.octave
which I had found at https://launchpad.net/javaoctave.

Thank you for your help,
Martin


-----Original Message-----
From: Jaroslav Hajek [mailto:[hidden email]]
Sent: Wednesday, September 10, 2008 1:14 PM
To: John W. Eaton
Cc: David Bateman; [hidden email]; Hepperle, Martin;
octave maintainers mailing list
Subject: Re: [OctDev] [Changeset] Re: Java calling Octave via JNI

On Tue, Sep 9, 2008 at 7:44 PM, John W. Eaton <[hidden email]>
wrote:

> On  5-Sep-2008, David Bateman wrote:
>
> | David Bateman wrote:
> | > MartinHepperle wrote:
> | >> Hello all,
> | >>
> | >> again this nasty Java -> Octave connection.
> | >>
> | >> I also want to embed Octave into a Java program and call Octave
> | >> functions from Java.
> | >>
> | >> Initially I started with programming an execution engine which
> | >> starts octave.exe and connected to its standard input and output
> | >> pipes. This concept works (in the meantime I also found two
> | >> solutions which implement the same technique) but is somewhat
> | >> ugly and inefficient due to conversions to and from strings
> | >>
> | >> What I tried now was to call the Octave DLLs (Windows platform)
> | >> directly via a C wrapper and using JNI.
> | >> This technique provides a very elegant solution and I have used
> | >> this in the past to call C and FORTRAN codes from Java. I want to

> | >> define some global variables, set the values from Java, execute
> | >> some user supplied functions and 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 an

> | >> executable (.exe) file
> | >>
> | >> // what does the follwing code do? It works, but where is the
> | >> variable in Octave?
> | >> 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 a thin layer between Java objects and the C interface to

> | >> Octave.
> | >> If I put the same code inside a DLL I can initialize Octave, but
> | >> the eval_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 something else than global variables
> | >> in Octave.
> | >>
> | >> Anyway, I see that eval_string() seems to work when called from a

> | >> C executable, but not when I call it from a DLL. Could this have
> | >> something to do 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,
> | >>
> | >> Martin
> | >>
> | >>
> | >>
> | >>
> | >>
> | > eval_string can only work if the interpreter is initialized..
> | > Check the mailing lists for how to initialize the interpreter.
> | >
> | > D.
> | >
> | >
> | 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.
>
> I applied it.
>

I transplanted this "explanationation" (hg description :-) patch to
3.0.x series




--
RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU) Prague, Czech Republic
url: www.highegg.matfyz.cz

Reply | Threaded
Open this post in threaded view
|

Re: [OctDev] [Changeset] Re: Java calling Octave via JNI

Michael Goffioul
On Wed, Sep 10, 2008 at 1:46 PM,  <[hidden email]> wrote:

> Hello all,
>
> after some further experimentation I have given up this route.
> I guess that there is some version conflict between C++ runtime
> DLLs which I could not resolve.  My DLL was able to load the
> octave DLLs, but when Octave tried to load its .oct libraries,
> which seem to be DLLs under Windows, it was unable to load
> them with LoadLibrary() ("cannot find library..., but the
> complete path is given, correct and the .oct library is there).
> I was using VS 2005 for my C-Java interface DLL which should be
> compatible with the Octave DLLS, but it may be that there is a
> conflict with differenr runtime libraries.
> I did not want to recompile the whole Octave system.

When you tried that, did you add octave bin directory to PATH
variable before starting your java program?

Michael.