2016-07-17 9 views
0

Aus "How to exit GNU Octave, after running an m file, without closing plot windows?" kam die Frage, ob man Vektoren von einem C++ - Programm zu einer GNU Octave-Funktion übergeben kann. Ich habe dieses C++ Programm:Wie übergeben Sie Vektoren zu GNU Octave-Funktionen in C++ - Programmen?

#include <iostream> 
#include <vector> 
#include <string> 
#include <fstream> 
#include <cmath> 
#include <utility> 
#include <unistd.h> 
#include <octave/oct.h> 
#include <octave/octave.h> 
#include <octave/parse.h> 
#include <octave/toplev.h> 
using namespace std; 

double N  = 1000.0; 
double t0 = 0.0; 
double t1 = 10.0; 
double x0 = 0.0; 
double dx0 = 0.0; 
double h  = (t1 - t0)/double(N); 

double dx2(double t, double x, double dx) 
{ 
    return {-9.8*cos(x + dx)}; 
} 

std::pair<double, double> RK4(double t, double x, double dx, double h) 
{ 
    // k values are diffs in dy/dx. 
    // l values are diffs in x. 
    double k1, k2, k3, k4, l1, l2, l3, l4, diff1, diff2; 
    k1 = h*dx2(t,x,dx); 
    l1 = h*dx; 
    k2 = h*dx2(t+h/2,x+l1/2,dx+k1/2); 
    l2 = h*(dx+k1/2); 
    k3 = h*dx2(t+h/2,x+l2/2,dx+k2/2); 
    l3 = h*(dx+k2/2); 
    k4 = h*dx2(t+h,x+l3,dx+k3); 
    l4 = h*(dx+k3); 
    diff1 = (l1+2*l2+2*l3+l4)/float(6); // diff in x. 
    diff2 = (k1+2*k2+2*k3+k4)/float(6); // diff in y. 
    return {diff1, diff2}; 
} 

int main() 
{ 
    std::vector<double> t; 
    t.push_back(t0); 
    std::vector<double> x; 
    x.push_back(x0); 
    std::vector<double> dx; 
    dx.push_back(dx0); 

    ofstream myfile; 
     ofstream myfiledx; 
    myfile.open("simppenadj.txt"); 
     myfiledx.open("simppenadjdx.txt"); 

    for(int i = 1; i<=N; i++) { 
     auto diff = RK4(t[i-1],x[i-1],dx[i-1],h); 
     t.push_back( t[i-1] + h); 
     x.push_back( x[i-1] + diff.first ); 
     dx.push_back(dx[i-1] + diff.second); 
     myfile << t[i-1]; 
     myfile << " " << x[i-1] << "\n"; 
       myfiledx << x[i-1]; 
       myfiledx << " " << dx[i-1] << "\n"; 
     usleep(1000); 
    } 
    myfile << t[N]; 
     myfile << " " << x[N]; 
     myfile.close(); 
     myfiledx << x[N]; 
     myfiledx << " " << dx[N]; 
     myfiledx.close(); 

    pid_t pid = fork(); 

    if(pid != 0) // parent 
    { 
     std::cout << "parent, exiting\n"; 
    } 
    else 
    { 
      // arguments for octave 
     string_vector argv (2); 
     argv(0) = "embedded"; 
     argv(1) = "-q"; // quiet 

     // start octave, run embedded (third parameter == true) 
     octave_main (2, argv.c_str_vec(), true); 

     // read the script file 
     source_file("simppenadj.m"); 

     // call the function with an argument 
     octave_value_list in; 
     in(0) = t; 
      in(1) = x; 
      in(2) = dx; 
     feval("simppenadj",in,1); 

     std::cout << "octave (child process) done\n"; 
     clean_up_and_exit(0); // quit octave. This also quits the program, 
            // so use this together with atexit, if you 
            // need to do something else after octave exits 
     } 
} 

die in(0), in(1) und in(2) Begrenzungslinien sind, wo das Problem in diesem Code existiert. Wie immer, wenn dieses Programm kompiliert wird und den Fehler:

/usr/bin/g++ -Wall -fPIC -L/usr/lib/octave/4.0.3 -I/usr/include/octave-4.0.3 -loctave -loctinterp -o "simppenadj.o" "simppenadj.cpp" && chmod +x simppenadj.o && ./simppenadj.o 
simppenadj.cpp: In function ‘int main()’: 
simppenadj.cpp:97:14: error: no match for ‘operator=’ (operand types are ‘octave_value’ and ‘std::vector<double>’) 
     in(0) = t; 
      ^
In file included from /usr/include/octave-4.0.3/octave/oct-obj.h:33:0, 
       from /usr/include/octave-4.0.3/octave/ov-fcn.h:31, 
       from /usr/include/octave-4.0.3/octave/ov-builtin.h:28, 
       from /usr/include/octave-4.0.3/octave/defun-int.h:28, 
       from /usr/include/octave-4.0.3/octave/defun-dld.h:30, 
       from /usr/include/octave-4.0.3/octave/oct.h:36, 
       from simppenadj.cpp:8: 
/usr/include/octave-4.0.3/octave/ov.h:356:17: note: candidate: octave_value& octave_value::operator=(const octave_value&) 
    octave_value& operator = (const octave_value& a) 
       ^~~~~~~~ 
/usr/include/octave-4.0.3/octave/ov.h:356:17: note: no known conversion for argument 1 from ‘std::vector<double>’ to ‘const octave_value&’ 
simppenadj.cpp:98:12: error: no match for ‘operator=’ (operand types are ‘octave_value’ and ‘std::vector<double>’) 
    in(1) = x; 
      ^
In file included from /usr/include/octave-4.0.3/octave/oct-obj.h:33:0, 
       from /usr/include/octave-4.0.3/octave/ov-fcn.h:31, 
       from /usr/include/octave-4.0.3/octave/ov-builtin.h:28, 
       from /usr/include/octave-4.0.3/octave/defun-int.h:28, 
       from /usr/include/octave-4.0.3/octave/defun-dld.h:30, 
       from /usr/include/octave-4.0.3/octave/oct.h:36, 
       from simppenadj.cpp:8: 
/usr/include/octave-4.0.3/octave/ov.h:356:17: note: candidate: octave_value& octave_value::operator=(const octave_value&) 
    octave_value& operator = (const octave_value& a) 
       ^~~~~~~~ 
/usr/include/octave-4.0.3/octave/ov.h:356:17: note: no known conversion for argument 1 from ‘std::vector<double>’ to ‘const octave_value&’ 
simppenadj.cpp:99:12: error: no match for ‘operator=’ (operand types are ‘octave_value’ and ‘std::vector<double>’) 
    in(2) = dx; 
      ^~ 
In file included from /usr/include/octave-4.0.3/octave/oct-obj.h:33:0, 
       from /usr/include/octave-4.0.3/octave/ov-fcn.h:31, 
       from /usr/include/octave-4.0.3/octave/ov-builtin.h:28, 
       from /usr/include/octave-4.0.3/octave/defun-int.h:28, 
       from /usr/include/octave-4.0.3/octave/defun-dld.h:30, 
       from /usr/include/octave-4.0.3/octave/oct.h:36, 
       from simppenadj.cpp:8: 
/usr/include/octave-4.0.3/octave/ov.h:356:17: note: candidate: octave_value& octave_value::operator=(const octave_value&) 
    octave_value& operator = (const octave_value& a) 
       ^~~~~~~~ 
/usr/include/octave-4.0.3/octave/ov.h:356:17: note: no known conversion for argument 1 from ‘std::vector<double>’ to ‘const octave_value&’ 
make: *** [Makefile:3: all] Error 1 

zurückgegeben wird. So gibt es offensichtlich ein Eingabeproblem mit std::vector<double> Eingaben. Die Frage ist also: "Wie werden Vektoren von C++ - Programmen an GNU Octave-Funktionen übergeben, die in diesen Programmen aufgerufen werden?"

+0

Warum verwenden Sie C++ überhaupt? Es scheint, dass alle Ihre Berechnungen leicht in Oktave durchgeführt werden können. Ich denke, das würde viele Probleme lösen. – pschulz

+0

Ich benutze es, weil ich versuche, C++ zu lernen, ich kenne die Syntax von GNU Octave schon ziemlich gut, aber ich verstehe C++ nicht sehr gut und möchte es. – BH2017

+0

Die API ist in https://www.gnu.org/software/octave/doc/interpreter/External-Code-Interface.html#External-Code-Interface beschrieben und Sie finden einige Beispiele in (na, wer ' Vermutlich?) in den ./Beispielen. Verwenden von Matrix und Vektoren zum Beispiel in https://www.gnu.org/software/octave/doc/interpreter/Matrices-and-Arrays-in-Oct_002dFiles.html#Matrices-and-Arrays-in-Oct_002dFiles TL; DR: Verwenden Sie Klasse Matrix und nicht std :: vector, obwohl es eine c'tor in ovl – Andy

Antwort

0

ich ist dies durch eine kleine Schleife zu tun:

std::vector<double> x; 
Matrix inMatrix_x(x.size(), 1); 
for(unsigned int i = 0; i < x.size(); i++) 
{ 
    inMatrix_x(i, 0) = x.at(i); // inMatrix_x(i) would also do the job 
} 
octave_value_list in; 
in(0) = inMatrix_x; 

Wenn Sie Daten von einem skript zurück zu erhalten, müssen Sie über outMatrix_y.length() iterize.