在 C 中调用 GNU Octave 函数?
Call GNU Octave functions in C?
我想使用矩阵代数和优化。我已经为矩阵代数测试了不同的 C 和 C++ 库,但这些库的问题是它们无法像 GNU Octave 那样处理垃圾数据。 C 和 C++ 中的垃圾数据低至 e-8,但在 GNU Octave 中,它将被压低至 e-17。如果您打算在计算中使用来自测量的垃圾数据,那将非常有用。它们不会影响您的结果。
但是 GNU Octave 有一个 C++ API,我不太明白如何使用。但是我想使用 C 并从 C 调用 GNU Octave 函数。
我是否可以创建一个包含二维数组和维度的结构,并将其发送到 GNU Octave,我将再次 return 一个具有结果和维度的结构,例如解决方案。
有一个 c mex interface. However the octave interpreter must be embedded and initialized before any mex function can be called. As of Octave 4.4 octave_main
as suggested by the linked answer 已被弃用,还需要进行一些其他更改才能使其对 mex 程序有用。所以我准备了一个包含函数 mexCallOctave
和 free_arg_list
及其头文件 calloctave.h
.
的 C++ 源文件 calloctave.cc
calloctave.cc
// calloctave.cc
#include "interpreter.h"
#include "mxarray.h"
#include "parse.h"
extern "C"
int
mexCallOctave (int nargout, mxArray *argout[], int nargin,
mxArray *argin[], const char *fname)
{
static octave::interpreter embedded_interpreter;
if (!embedded_interpreter.initialized())
embedded_interpreter.execute ();
octave_value_list args;
args.resize (nargin);
for (int i = 0; i < nargin; i++)
args(i) = mxArray::as_octave_value (argin[i]);
bool execution_error = false;
octave_value_list retval;
retval = octave::feval (fname, args, nargout);
int num_to_copy = retval.length ();
if (nargout < retval.length ())
num_to_copy = nargout;
for (int i = 0; i < num_to_copy; i++)
{
argout[i] = new mxArray (retval(i));
}
while (num_to_copy < nargout)
argout[num_to_copy++] = nullptr;
return execution_error ? 1 : 0;
}
extern "C"
void
free_arg_list (int nargs, mxArray* arglist[])
{
for(int i = 0; i < nargs; i++)
delete arglist[i];
}
calloctave.h
// calloctave.h
#pragma once
#include "mex.h"
#if defined (__cplusplus)
extern "C" {
#endif
int
mexCallOctave (int nargout, mxArray *argout[], int nargin,
mxArray *argin[], const char *fname);
void
free_arg_list (int nargs, mxArray* arglist[]);
#if defined (__cplusplus)
}
#endif
Here 是对 mex 文件的基本介绍。您可以编译一个示例 hello world 程序,将选项 --verbose
添加为 mkoctfile --mex --verbose hello.c
以获取您需要使用它们来编译实际程序的编译器选项列表。请注意,因为 calloctave.cc
是一个 c++ 源代码,所以应该使用 c++ 编译器(例如 g++)对其进行编译。
在下面的示例中,调用了一个 m 函数 "myfunction"。它获得一个输入并产生一个输出。 mexCallOctave
用于调用octave函数,与mexCallMATLAB具有相同的签名。
myfunction.m
% myfunction.m
function out= myfunction( a )
out = sum(a);
endfunction
main.c
//main.c
#include <stdio.h>
#include "calloctave.h"
int main()
{
double input_data[] = {0,1,2,3,4,5,6,7,8,9,10};
const int nargin = 1;
const int nargout = 1;
mxArray* rhs[nargin];
mxArray* lhs[nargout];
// allocate mex array
rhs[0] = mxCreateDoubleMatrix( 10, 1, mxREAL);
double* rhs_ptr = mxGetPr( rhs[0] );
// copy data from input buffer to mex array
for (int i = 0 ; i < 10; i++)
rhs_ptr[i] = input_data[i];
// call octave function
mexCallOctave(nargout, lhs, nargin, rhs, "myfunction");
double* lhs_ptr = mxGetPr( lhs[0] );
double output_data = *lhs_ptr;
// show the result
printf ("result = %f", output_data);
// free memory
mxDestroyArray(rhs[0]);
free_arg_list(nargout, lhs);
}
我想使用矩阵代数和优化。我已经为矩阵代数测试了不同的 C 和 C++ 库,但这些库的问题是它们无法像 GNU Octave 那样处理垃圾数据。 C 和 C++ 中的垃圾数据低至 e-8,但在 GNU Octave 中,它将被压低至 e-17。如果您打算在计算中使用来自测量的垃圾数据,那将非常有用。它们不会影响您的结果。
但是 GNU Octave 有一个 C++ API,我不太明白如何使用。但是我想使用 C 并从 C 调用 GNU Octave 函数。
我是否可以创建一个包含二维数组和维度的结构,并将其发送到 GNU Octave,我将再次 return 一个具有结果和维度的结构,例如解决方案。
有一个 c mex interface. However the octave interpreter must be embedded and initialized before any mex function can be called. As of Octave 4.4 octave_main
as suggested by the linked answer 已被弃用,还需要进行一些其他更改才能使其对 mex 程序有用。所以我准备了一个包含函数 mexCallOctave
和 free_arg_list
及其头文件 calloctave.h
.
calloctave.cc
calloctave.cc
// calloctave.cc
#include "interpreter.h"
#include "mxarray.h"
#include "parse.h"
extern "C"
int
mexCallOctave (int nargout, mxArray *argout[], int nargin,
mxArray *argin[], const char *fname)
{
static octave::interpreter embedded_interpreter;
if (!embedded_interpreter.initialized())
embedded_interpreter.execute ();
octave_value_list args;
args.resize (nargin);
for (int i = 0; i < nargin; i++)
args(i) = mxArray::as_octave_value (argin[i]);
bool execution_error = false;
octave_value_list retval;
retval = octave::feval (fname, args, nargout);
int num_to_copy = retval.length ();
if (nargout < retval.length ())
num_to_copy = nargout;
for (int i = 0; i < num_to_copy; i++)
{
argout[i] = new mxArray (retval(i));
}
while (num_to_copy < nargout)
argout[num_to_copy++] = nullptr;
return execution_error ? 1 : 0;
}
extern "C"
void
free_arg_list (int nargs, mxArray* arglist[])
{
for(int i = 0; i < nargs; i++)
delete arglist[i];
}
calloctave.h
// calloctave.h
#pragma once
#include "mex.h"
#if defined (__cplusplus)
extern "C" {
#endif
int
mexCallOctave (int nargout, mxArray *argout[], int nargin,
mxArray *argin[], const char *fname);
void
free_arg_list (int nargs, mxArray* arglist[]);
#if defined (__cplusplus)
}
#endif
Here 是对 mex 文件的基本介绍。您可以编译一个示例 hello world 程序,将选项 --verbose
添加为 mkoctfile --mex --verbose hello.c
以获取您需要使用它们来编译实际程序的编译器选项列表。请注意,因为 calloctave.cc
是一个 c++ 源代码,所以应该使用 c++ 编译器(例如 g++)对其进行编译。
在下面的示例中,调用了一个 m 函数 "myfunction"。它获得一个输入并产生一个输出。 mexCallOctave
用于调用octave函数,与mexCallMATLAB具有相同的签名。
myfunction.m
% myfunction.m
function out= myfunction( a )
out = sum(a);
endfunction
main.c
//main.c
#include <stdio.h>
#include "calloctave.h"
int main()
{
double input_data[] = {0,1,2,3,4,5,6,7,8,9,10};
const int nargin = 1;
const int nargout = 1;
mxArray* rhs[nargin];
mxArray* lhs[nargout];
// allocate mex array
rhs[0] = mxCreateDoubleMatrix( 10, 1, mxREAL);
double* rhs_ptr = mxGetPr( rhs[0] );
// copy data from input buffer to mex array
for (int i = 0 ; i < 10; i++)
rhs_ptr[i] = input_data[i];
// call octave function
mexCallOctave(nargout, lhs, nargin, rhs, "myfunction");
double* lhs_ptr = mxGetPr( lhs[0] );
double output_data = *lhs_ptr;
// show the result
printf ("result = %f", output_data);
// free memory
mxDestroyArray(rhs[0]);
free_arg_list(nargout, lhs);
}