Вызывать функции GNU Octave в C? - PullRequest
1 голос
/ 16 мая 2019

Я хочу использовать матричную алгебру и оптимизацию.Я тестировал разные библиотеки C и C ++ для матричной алгебры, но проблема в том, что они не могут обрабатывать мусорные данные так же хорошо, как GNU Octave.Мусорные данные в C и C ++ снижаются до уровня e-8, но в GNU Octave они снижаются до уровня e-17.Это очень полезно, если вы планируете использовать данные мусора, например, из измерений в расчетах.Они никак не влияют на ваши результаты.

Но у GNU Octave есть C ++ API, который я не совсем понимаю, как его использовать.Но я хочу использовать C и вызывать функции GNU Octave из C.

Возможно ли, что я могу создать структуру, содержащую двумерный массив и измерения, и отправить ее в GNU Octave, и я снова верну структурукоторые имеют результат и размер, например, решение.

1 Ответ

4 голосов
/ 18 мая 2019

Имеется интерфейс c mex . Однако октавный интерпретатор должен быть встроен и инициализирован перед вызовом любой mex-функции. По состоянию на октаву 4.4 octave_main, как предполагает связанный ответ , устарел, и некоторые другие изменения также необходимы для того, чтобы он был полезен для программ mex. Итак, я подготовил исходный файл C ++ calloctave.cc, содержащий функции mexCallOctave и free_arg_list и его заголовок calloctave.h.

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

Здесь - базовое введение в mex-файлы. Вы можете скомпилировать пример программы hello world, добавив опцию --verbose как mkoctfile --mex --verbose hello.c, чтобы получить список опций компилятора, которые вам понадобятся для компиляции ваших реальных программ. Обратите внимание, что, поскольку calloctave.cc является исходным кодом c ++, его следует компилировать с использованием компилятора c ++, такого как g ++. В следующем примере вызывается функция «myfunction». Он получает один вход и производит один выход. mexCallOctave используется для вызова функции октавы и имеет ту же сигнатуру, что и 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);
}
...