Introduction
“GNU Octave is a high-level interpreted language,
primarily intended for numerical computations. It provides capabilities for the
numerical solution of linear and nonlinear problems, and for performing other
numerical experiments. It also provides extensive graphics capabilities for
data visualization and manipulation. Octave is normally used through its
interactive command line interface, but it can also be used to write
non-interactive programs. The Octave language is quite similar to Matlab so
that most programs are easily portable.
Octave is distributed under the terms of the GNU General Public
License. “
(Text and image above belong to http://www.gnu.org/software/octave/)
Recently I had to use some Octave scripts within a C# project I’m currently
working on. After searching for a solution I had to implement my own Octave
wrapper.
The basic idea is to start a process and redirect
the standard input, output and error streams in order to execute random
commands with the Octave interpreter. One common problem is that after successfully
running a command, the interpreter blocks the output stream and there is no way
to know when Octave finished its job. A solution to this problem is as follows:
given the fact that the last line in the execution of the process is always
available you can create a random string and make Octave echo this string every
time you run another command; when parsing the output, an indication that the
previous command is surly executed is when you encounter your echoed string.
Implementation
When starting the octave process a new random
echo string is generated:
private string StartOctave(string PathToOctaveBinaries, bool CreateWindow) {
this.OctaveEchoString = Guid.NewGuid().ToString();
OctaveProcess = new Process();
.
.
.
OctaveProcess.OutputDataReceived +=
new DataReceivedEventHandler(OctaveProcess_OutputDataReceived);
OctaveProcess.BeginOutputReadLine();
OctaveEntryText = ExecuteCommand(null);
}
When executing a random command the current
thread blocks until a ManualResetEvent is triggered:
public string ExecuteCommand(string command) {
if (OctaveProcess.HasExited)
OctaveProcess.Start();
SharedBuilder.Clear();
if (command != null) {
OctaveProcess.StandardInput.WriteLine(command);
}
OctaveProcess.StandardInput.WriteLine("\""+ OctaveEchoString + "\"");
OctaveDoneEvent.Reset();
OctaveDoneEvent.WaitOne();
return SharedBuilder.ToString();
}
And the asynchronous
output data received puts all data in a StringBuilder until it comes across the
echoed string.
void OctaveProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) {
if (e.Data == null) {
SharedBuilder.Clear();
SharedBuilder.Append("Octave has exited with the following error message: \r\n" + OctaveProcess.StandardError.ReadToEnd());
OctaveDoneEvent.Set();
return;
}
if (e.Data.Trim() == "ans = " + OctaveEchoString)
OctaveDoneEvent.Set();
else
SharedBuilder.Append(e.Data + "\r\n");
}
Using the code
Just create a new
Octave class instance using one of the two constructors and pass on the full path
to your octave installation.
After doing so, you
can access the Octave command interpreter using the “ExecuteCommand
” method.
Reading results is done in the form of scalars(GetScalar
), vectors(GetVector
)
and matrices(GetMatrix
).
A simple script that
calculates the transpose of a matrix is given below:
octave = new Octave(@"D:\Download\Soft\Octave3.6.0_gcc4.6.2\bin", false);
octave.ExecuteCommand("a=[1,2;3,4];");
octave.ExecuteCommand("result=a';");
double[][] m = octave.GetMatrix("result");
Hope this helps and if
you use any of this work make sure to add a reference: Boros Tiberiu, OctaveSharp - running GNU Octave with C#, CodeProject, 2012