如何在运行m文件后退出GNU Octave,而不关闭绘图窗口?

4

我一直在编写一个C++程序来解决简单摆的问题,然后使用GNU Octave绘制结果。我的程序通过以下代码行来绘制结果:

system("./simppenadj.sh");

其中simppenadj.sh是:

#!/bin/sh
octave --no-gui --persist -q simppenadj.m

simppenadj.m 是:

#!/usr/bin/octave
# Plotting simppenadj.txt
A      = importdata('simppenadj.txt');
B      = importdata('simppenadjdx.txt');
t      = A(:,1);
theta  = A(:,2);
dtheta = B(:,2);
figure
plot(t,theta)
xlabel('t','FontSize',16,'FontWeight','bold')
ylabel('\theta','FontSize',16,'FontWeight','bold')
title('{d^{2}\theta}/{d{t^{2}}} = -9.8 cos({\theta})','FontSize',18,'FontWeight','bold')
figure
plot(theta,dtheta)
xlabel('\theta','FontSize',16,'FontWeight','bold')
ylabel('d\theta/dt','FontSize',16,'FontWeight','bold')
title('{d^{2}\theta}/{d{t^{2}}} = -9.8 cos({\theta})','FontSize',18,'FontWeight','bold')

每当我运行我的C++程序时,GNU Octave的CLI会启动(并在最后保留打开状态),然后数据将被绘制。我不希望GNU Octave的CLI保持打开状态,但我知道的唯一方法是删除simppenadj.sh中的--persist选项,这也会使GNU Octave生成的图形不再保持打开状态。这是一个问题,因为我希望在运行完我的C++程序后,图形能够保持打开状态。那么有没有办法做到这一点呢?

为什么不直接将图形保存为图片呢?我想不出有哪些程序在退出时会保留窗口开启。 - Suever
原因更多是出于个人喜好而非其他任何原因。但如果无法实现,我将选择保存为SVG格式。 - Josh Pinto
我刚刚发现使用绘图而不是保存为SVG的另一个原因...我的LaTeX标签在SVG输出中未被渲染,而在绘图本身中它们被正确地渲染。 - Josh Pinto
2个回答

5
您可以使用Octave API从程序内部调用脚本。在那里,创建一个子进程,调用Octave,以便父进程可以结束。通过这种方式,您可以保持Octave运行。使用此方法,没有Octave CLI,因为您通过API执行所有对Octave的调用,特别是feval
不幸的是,关于使用API的指南非常糟糕,但我为您准备了一些东西,应该可以工作。它基本上只读取脚本并执行相应的函数。这就是这种方法的好处:您可以使用普通的Octave函数/脚本文件方法编写所有内容。
我在Octave文件中添加了printf语句,以显示如何将参数传递给Octave。

main.cpp

#include <iostream>

#include <unistd.h>

#include <octave/oct.h>
#include <octave/octave.h>
#include <octave/parse.h>
#include <octave/toplev.h>

int main()
{
    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("calc_and_plot.m");

        // call the function with an argument
        octave_value_list in;
        in(0) = "Hello, world.";
        feval("calc_and_plot", in);


        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
    }

    return 0;
}

Octave 脚本/函数文件

function calc_and_plot(str)
    printf('%s\n', str);
    x = linspace(0, 2*pi, 100);
    y = sin(x);
    it = plot(y);
    waitfor(it);
end

使用以下命令编译 main.cpp:

g++ main.cpp -L/usr/lib/octave-4.0.2 -I/usr/include/octave-4.0.2 -loctave -loctinterp

你需要根据你的系统和 octave 版本调整路径。你也可以使用 mkoctfile 命令,它基本上做了相同的事情。你可以查看其 -p 开关的输出,例如:

mkoctfile -p CFLAGS

要获取库、编译器标志等,请查看此命令的手册页面。


你确定吗?对我来说,这会返回 这个错误 - Josh Pinto
你必须链接正确的库。我编辑了我的答案。 - pschulz
你已经编辑过了还是将要编辑?因为你上次的编辑是3小时前,而我实现的是你编辑后的答案而不是原始答案,这就是在那个paste2.org链接中返回错误的原因。 - Josh Pinto
你的Octave函数是否可以传递向量?所谓的“向量”是指三个单独的向量,提供给Octave函数。 - Josh Pinto
如果您有兴趣回答,我提出了一个与此查询相关的新问题 http://stackoverflow.com/questions/38421857/how-to-pass-vectors-to-gnu-octave-functions-in-c-programs。 - Josh Pinto
3
等待(waitfor)它的操作是纯金(xD)。 - Tasos Papastylianou

0

我假设您遇到了以下问题:

  • 在 octave 提示符中保持持久结果,这会导致您的 c++ 程序停止运行,直到您退出。
  • 删除 persist 会关闭图形,但是您的 c++ 程序会正常运行。

假设您在 Linux 终端上,这更像是一种 hack,但您可以在 octave 文件中添加一个暂停命令(实际上是一个小暂停,然后是一个无限暂停,如果您想确保所有图像都被刷新),然后在 c++ 中使用“&”调用您的脚本,使其进入“守护进程”模式。

这样做的结果是 octave 代码将在后台运行,这意味着您的绘图保持打开状态,而您的 c++ 程序不会停止。

话虽如此,一旦您的 c++ 程序退出,绘图 也会 关闭。如果您不希望出现这种情况,并且希望即使在 c++ 程序“完成”后,绘图也保持打开状态,则可以进一步使用 pause() 或 sigsuspend() 函数来进行 hack,然后在您的 c++ 代码末尾使用 & 调用您的 c 可执行文件。(完成后,手动从终端中杀死它,或者只需退出终端即可)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接