如何在不安装Octave的情况下创建简单的Octave可分发

时间:2010-10-01 22:51:52

标签: octave

关于这个主题的Octave文档既令人生畏又稀疏。

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

以下解决方案适用于简单的windows distributable。

使用案例
在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=[]; 

7 个答案:

答案 0 :(得分: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文件,并且可以运行该文件。唯一的问题是,它将缺少使八度音程变得令人敬畏的所有好东西。你必须提供这些。

第2步:创建分发文件夹

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

第3步:其他文件whack-a-mole

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

现在,你必须玩“鼹鼠或者历史悠久的传统”“我的包含在哪里,哟?”

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

      

    embedded.exe
      错误:'max'未定义在第83行第22列附近   错误:评估参数列表元素编号1
      错误:评估参数列表元素编号1
      错误:来自:   错误:T:\ sms \ Development \ research \ c2 \ disttest \ strcat.m,第83行第3列   错误:第5行第10列的T:\ sms \ Development \ research \ c2 \ disttest \ file_in_path.m
      错误:T:\ sms \ Development \ research \ c2 \ disttest \ imread.m,第50行第6行

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

    B 您搜索的内容非常明显,如“min”,并且没有结果。这是因为可装载功能“min”位于.oct文件“max.oct”中。制作max.oct的副本,并将其重命名为min.oct。它现在可以工作了。你怎么知道这些功能在哪里?我不确定。他们中的大多数都在明显的地方,例如“max.oct”表示min,“fft2.oct”表示“ifft2.oct”。祝你好运。

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

答案 1 :(得分: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

的函数

答案 2 :(得分:1)

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

  1. 需要#include <octave/toplev.h>
  2. return 0;(如上所述)替换为clean_up_and_exit(0);
  3. 如果没有这些步骤,我的程序会在退出时反复崩溃。

答案 3 :(得分:1)

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

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

刚刚救了你半天( - ;

答案 4 :(得分:1)

在子弹4 B的上述解决方案中:

  

B你搜索像&#34; min&#34;这样的东西,并没有得到任何结果。   这是因为可装载功能&#34; min&#34;在.oct文件中   &#34; max.oct&#34 ;.制作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。 / p>

答案 5 :(得分:0)

查看Stratego Octave Compiler

(我还没有测试过,但计划在接下来的几天内进行测试。)

答案 6 :(得分:0)

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

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

当然这会造成巨大的磁盘空间浪费,下载280MB的压缩文件,解压缩到1GB以上(后来由于没有删除拉链,我的情况更糟),而且你被困在一个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." )