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

Octave 如何在不安装倍频程的情况下创建可分发的简单倍频程,octave,Octave,关于这个主题的八度音阶文档既吓人又稀少 我不知道还有什么地方可以记录我找到的解决方案,所以我在这里发布。如果这不合适,我道歉,但我想帮助下一个人 以下解决方案适用于一个简单的windows可分发应用程序 用例: Octave 3.2.4中开发了一个解决方案,需要分发给不具备计算机技能的最终用户。安装和解释倍频程是不可能的,解决方案必须是“一键式”或“简单得让人头脑发热” 已知问题: imread在3.2.4中失败,因为路径m中的文件错误。您需要将_path.m中的文件_更新为以下内容(只需替换它

关于这个主题的八度音阶文档既吓人又稀少

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

以下解决方案适用于一个简单的windows可分发应用程序

用例:
Octave 3.2.4中开发了一个解决方案,需要分发给不具备计算机技能的最终用户。安装和解释倍频程是不可能的,解决方案必须是“一键式”或“简单得让人头脑发热”

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

函数名=路径中的文件(p,文件)
idx=[1 findstr(p,pathsep)长度(p)+1];
对于i=1:长度(idx)-1
如果idx(i+1)-idx(i)=0
fclose(fid);
返回
结束
结束
fid=fopen(文件“r”);
如果fid>=0,
fclose(fid);
名称=文件;
返回
结束
名称=[];

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

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

您可以在此处看到有效的代码:

尤其是文件“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;
}
它可能会抛出警告,但只要它不会抛出错误,您就可以了。将生成embedded.exe文件,并可以运行该文件。唯一的问题是,它将缺乏所有的好东西,使八度真棒。你必须提供这些

步骤2:创建分发文件夹

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

第三步:其他文件打鼹鼠

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

现在,你必须扮演“打鼹鼠”或“我的朋友在哪里,哟?”这一古老的传统

  • 打开cmd提示符并导航到您的分发文件夹
  • 去掉任何有用的路径字符串。你的客户不会拥有它们
  • 尝试运行程序embedded.exe。您将得到如下错误:

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

  • A在倍频程装置中搜索“max”。它将是.oct或.m文件。在本例中,它是一个.oct文件max.oct。将其复制到您的分发目录

    B你搜索像“min”这样明显的词,但没有结果。这是因为可加载函数“min”位于.oct文件“max.oct”中。复制max.oct,并将其重命名为min.oct。现在可以了。你怎么知道函数在哪里?我不确定。大多数都在明显的位置,如“max.oct”表示min,而“fft2.oct”表示“ifft2.oct”。祝你好运

  • 重复此操作,直到可执行文件运行为止


  • 如果您想运行脚本而不是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\u gcc4.6.2\lib\Octave\3.6.2\oct\i686-pc-mingw32\max.oct中的一个函数

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

  • 需要的
    #包括
  • 替换
    返回0(如上所述)带有
    清理和退出(0)
  • 没有这些步骤,我的程序在退出时反复崩溃

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

    来自倍频程解决方案,而不是来自批处理文件

    刚刚为您节省了半天时间(-;

    退房


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

    在上述bullet 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的路径


    上述理解基于通信包中的PKG_ADD和PKG_DEL文件,该文件位于\Octave-4.0.1\lib\Octave\packages\communications-1.2.1\i686-w64-mingw32-api-v50+\

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

    这将下载Octave 4.2.1作为一个可移植程序(32位,否则我们必须再次下载,如果系统是32位),使用vbs脚本解包,将内容移动到与ba相同的文件夹
    autoload ("min", "max.oct");
    
    autoload ("min", "max.oct", "remove");
    
    ::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
    '
    ' 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." )