21

关于这个主题的 Octave 文档既吓人又稀少。

我不知道在哪里可以记录我找到的解决方案,所以我在这里发布。如果这不合适,我很抱歉,但我想帮助下一个人。

以下解决方案适用于简单的 Windows 可分发。

用例:
在 Octave 3.2.4 中开发了一个解决方案,需要分发给计算机技能很少的最终用户。安装和解释 Octave 是不可能的,解决方案必须是“一键式”或“脑死简单”。

已知问题:
imread 在 3.2.4 中失败,因为 file_in_path.m 错误。您需要将文件 file_in_path.m 更新为以下内容(只需替换它):

function name=file_in_path(p,file)
  idx=[1 findstr(p,pathsep) length(p)+1];
  for i=1:length(idx)-1
    if idx(i+1)-idx(i)<=1
      dir=strcat(pwd,"/");
    else
      dir=p(idx(i)+1:idx(i+1)-1);
    end
    name = fullfile(dir, file);
    fid = fopen(name,"r");
    if fid >= 0
      fclose(fid);
      return
    end
  end
  fid = fopen(file,"r");
  if fid >= 0,
    fclose(fid);
    name=file;
    return
  end
  name=[]; 
4

7 回答 7

11

解决方案:使用 mkoctfile 创建一个可分发的 exe,并将此 exe 与核心 Octave 文件以及其他必要的 .oct 和 .m 文件打包。

步骤 1:创建一个独立的可执行文件。

您可以在此处查看有效的代码: http ://www.gnu.org/software/octave/doc/interpreter/Standalone-Programs.html

特别是文件“embedded.cc”。

我已将该文件简化如下:

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

int
main (int argc, char *argvc[])
{
  string_vector argv (2);
  argv(0) = "embedded";
  argv(1) = "-q";

  octave_main (2, argv.c_str_vec(), 1);

  octave_value_list in = octave_value (argvc[1]);
  octave_value_list out = feval ("your_custom_m_file", in);

  if (!error_state && out.length () > 0)
    {
    }
    else
    {
        std::cout << "invalid\n";
    }

  return 0;
}

使用命令构建此文件

mkoctfile --link-stand-alone embedded.cc -o embedded

它可能会抛出警告,但只要它没有抛出错误,你应该没问题。文件 Embedded.exe 将被构建,并且可以运行。唯一的问题是它将缺少使 octave 变得很棒的所有好东西。你必须提供这些。

步骤 2:创建分发文件夹

您将需要创建许多 Octave 文件的副本。我建议专门为此建立一个目录。至少,您将需要 \bin 中所有或大部分 DLL 的副本。此外,将可分发的可执行文件放在此目录中。

第 3 步:其他文件打地鼠

您现在需要找出运行 .m 脚本所需的其他文件。您可以通过将 \oct\i686-pc-mingw32*.oct 和 \share\octave\3.2.4\m\*\*.m 复制到分发目录来简化此步骤,尽管这将是矫枉过正,实际上不会防止打地鼠的步骤。

现在,您必须玩打地鼠游戏或“我的包括在哪里,哟?”的历史悠久的传统。

  1. 打开 cmd 提示符并导航到您的分发文件夹。
  2. 摆脱任何有用的 PATH 字符串。您的客户不会拥有它们。
  3. 尝试运行程序 embedded.exe。您将收到如下错误:

    Embedded.exe
    错误:第 83 行第 22 列附近的“最大”未定义
    错误:评估参数列表元素编号 1
    错误:评估参数列表元素编号 1
    错误:调用自:
    错误:T:\sms\Development\research\c2\disttest\ strcat.m 第 83 行第 3 列
    错误:T:\sms\Development\research\c2\disttest\file_in_path.m 第 5 行第 10 列
    错误:T:\sms\Development\research\c2\disttest\imread。 m 在第 50 行第 6 列

  4. 您的 Octave 安装中搜索“max”。它将是 .oct 或 .m 文件。在这种情况下,它是一个 .oct 文件,max.oct。将其复制到您的分发目录。

    B你搜索一些明显的东西,比如“min”,但没有得到任何结果。这是因为可加载函数“min”在 .oct 文件“max.oct”中。制作 max.oct 的副本,并将其重命名为 min.oct。它现在可以工作了。你怎么知道函数在哪里?我不确定。它们中的大多数都在明显的地方,例如 min 的“max.oct”和“ifft2.oct”的“fft2.oct”。祝你好运。

  5. 重复直到您的可执行文件运行。

于 2012-08-19T08:25:10.733 回答
5

只是补充一点,如果你想运行一个脚本而不是一个 m 函数,那么 Embedded.cc 的行:

octave_value_list out = feval ("your_custom_m_file", in);

应该:

octave_value_list out = feval ("your_custom_m_script");

还可以使用 'which' 来查找缺少的函数的打包位置。例如对于 min 函数:

octave:22> which min

min是文件 C:\Octave\Octave3.6.2_gcc4.6.2\lib\octave\3.6.2\oct\i686-pc-mingw32\max.oct 中的一个函数

于 2013-01-09T15:11:49.100 回答
2

将我的自定义 m 文件链接到 Octave 独立文件时发现的一些东西:

  1. 需要#include <octave/toplev.h>
  2. return 0;(如上)替换为clean_up_and_exit(0);

如果没有这些步骤,我的程序在退出时反复崩溃。

于 2015-07-08T16:08:17.587 回答
1

mkoctfile --link-stand-alone embedded.cc -o embedded

来自八度音程解决方案,而不是来自批处理文件。

刚救了你半天(-;

于 2015-09-03T15:16:17.323 回答
1

在上述项目符号 4 B 中的解决方案中:

B 你搜索一些明显的东西,比如“min”,但没有得到任何结果。这是因为可加载函数“min”在 .oct 文件“max.oct”中。制作 max.oct 的副本,并将其重命名为 min.oct。它现在可以工作了。

如果从 @folder function.m 调用某些函数,并且为了避免不必要的重复文件,这可能不起作用,只需在 @folder 之外的 m 文件中的某处添加以下代码

autoload ("min", "max.oct");

同样,它可以通过

autoload ("min", "max.oct", "remove");

确保此处提供了 max.oct 的路径。

以上理解是基于位于\Octave-4.0.1\lib\octave\packages\communications-1.2.1\i686-w64-mingw32-api-v50+\的通信包中的一个文件PKG_ADD和PKG_DEL

于 2016-03-31T13:52:20.017 回答
0

查看Stratego Octave 编译器

(我尚未对其进行测试,但计划在接下来的几天内进行。)

于 2015-12-27T20:56:44.140 回答
0

我有同样的要求(一键式,脑死简单),所以我做了一个只包含 curl.exe 的设置,下面的批处理文件,一个伪装成 .bat 的 exe(只需调用批处理文件下面)和下面的 .vbs 脚本(不是我写的)。当然还有我的 m 文件。

这会将 Octave 4.2.1 下载为可移植程序(32 位,否则如果系统是 32 位,我们必须再次下载),使用 vbs 脚本解压缩,将内容移动到与批处理相同的文件夹文件并在 GUI 模式下运行它。每次下次调用相同的脚本时,它只会检查 octave.bat 是否仍然存在。

当然,这会导致磁盘空间的巨大浪费,下载 280MB 的 zip,解压到超过 1GB(我之后不删除 zip 会更糟),而且你会遇到一个不容易打开的 cmd 窗口隐藏。

但它确实提供了我能找到的最简单的解决方案。它也不太可能在未来中断(无论是您自己的更新,还是 Octave 的更新)。在某个辉煌的一天,mkoktfile 实际上会很容易使用,并且会自行解决依赖关系,但直到那一天,这仍然是我能找到的最不让人头疼的解决方案。而且阿司匹林比别人的磁盘空间更贵。

::this file will test if the octave portable is downloaded and unpacked
@ECHO OFF

SET my_m_file=your_mfile.m
SET name_of_this_script=run_me.bat

::if the file exists, skip to the actual running.
IF EXIST "octave.bat" goto OctaveIsExtracted
IF EXIST "octave-4.2.1-w32.zip" goto OctaveIsDownloaded
ECHO The runtime (Octave portable 4.2.1) will now be downloaded.
ECHO This may take a long time, as it is about 280MB.
ECHO .
ECHO If this download restarts multiple times, you can manually download the octave-4.2.1-w32.zip from the GNU website. Make sure to unpack the contents.
::if this errors, you can uncomment the line with archive.org (which doesn't report total size during download)
curl http://ftp.gnu.org/gnu/octave/windows/octave-4.2.1-w32.zip > octave-4.2.1-w32.zip
::curl http://web.archive.org/web/20170827205614/https://ftp.gnu.org/gnu/octave/windows/octave-4.2.1-w32.zip > octave-4.2.1-w32.zip
:OctaveIsDownloaded
::check to see if the file size is the correct size to assume a successful download
::if the file size is incorrect, delete the file, restart this script to attempt a new download
::file size should be 293570269 bytes
call :filesize octave-4.2.1-w32.zip
IF /I "%size%" GEQ "293560000" goto OctaveIsDownloadedSuccessfully
del octave-4.2.1-w32.zip
::start new instance and exit and release this one
start %name_of_this_script%
exit
:OctaveIsDownloadedSuccessfully
IF EXIST "octave.bat" goto OctaveIsExtracted
::unzip and move those contents to the current folder
ECHO Unzipping octave portable, this may take a moment.
cscript //B j_unzip.vbs octave-4.2.1-w32.zip
SET src_folder=octave-4.2.1
SET tar_folder=%cd%
for /f %%a IN ('dir "%src_folder%" /b') do move %src_folder%\%%a %tar_folder%
pause
:OctaveIsExtracted
octave.bat %my_m_file%
goto :eof

:filesize
  set size=%~z1
  exit /b 0

和 j_unzip.vbs

' j_unzip.vbs
'
' UnZip a file script
'
' By Justin Godden 2010
'
' It's a mess, I know!!!
'

' Dim ArgObj, var1, var2
Set ArgObj = WScript.Arguments

If (Wscript.Arguments.Count > 0) Then
 var1 = ArgObj(0)
Else
 var1 = ""
End if

If var1 = "" then
 strFileZIP = "example.zip"
Else
 strFileZIP = var1
End if

'The location of the zip file.
REM Set WshShell = CreateObject("Wscript.Shell")
REM CurDir = WshShell.ExpandEnvironmentStrings("%%cd%%")
Dim sCurPath
sCurPath = CreateObject("Scripting.FileSystemObject").GetAbsolutePathName(".")
strZipFile = sCurPath & "\" & strFileZIP
'The folder the contents should be extracted to.
outFolder = sCurPath
'original line: outFolder = sCurPath & "\"

 WScript.Echo ( "Extracting file " & strFileZIP)

Set objShell = CreateObject( "Shell.Application" )
Set objSource = objShell.NameSpace(strZipFile).Items()
Set objTarget = objShell.NameSpace(outFolder)
intOptions = 256
objTarget.CopyHere objSource, intOptions

 WScript.Echo ( "Extracted." )
于 2017-08-30T22:42:57.363 回答