关于这个主题的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=[];
答案 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复制到分发目录来简化此步骤,尽管这样做会有些过分,并且实际上不会防止打鼹鼠的步骤。
现在,你必须玩“鼹鼠或者历史悠久的传统”“我的包含在哪里,哟?”
尝试运行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行
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”。祝你好运。
重复直到您的可执行文件运行。
答案 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独立文件时发现的东西:
#include <octave/toplev.h>
return 0;
(如上所述)替换为clean_up_and_exit(0);
如果没有这些步骤,我的程序会在退出时反复崩溃。
答案 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)
(我还没有测试过,但计划在接下来的几天内进行测试。)
答案 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." )