从单个 *.cc* 源文件生成多个 *.oct* 文件以将 C 库连接到 Octave

Generating multiple *.oct* files from a single *.cc* source file to interface a C library to Octave

我有一个 C 库,我想在 Octave. Following the tutorial 中使用它,这似乎很简单:用 C++ 包装函数,然后 mkoctfile 它们。问题是:如果我想在单个源文件中有多个函数定义(包装器)怎么办?

在提到的教程中有说明

It should be noted that it is perfectly acceptable to have more than one DEFUN_DLD function in a source file. However, there must either be a symbolic link to the oct-file for each of the functions defined in the source code with the DEFUN_DLD macro or the autoload (Function Files) function should be used.

然后在提供的link:

Once Octave finds a file with a name that matches (the called function), the contents of the file are read. If it defines a single function, it is compiled and executed. See Script Files, for more information about how you can define more than one function in a single file.

在第二个 link 中,没有关于如何加载包含多个函数的 .oct 文件或如何生成多个 [=21] 的信息=].oct 个源文件中的文件。据我了解,后者是正确的方法。我该怎么做?

第二个link的要点是你不要加载一个.oct文件它——至少从 Octave 的角度来看不是。这就是 symlink 的用途——你有符号 ABC 吗?使 A.octB.octC.oct 符号化 link 指向该文件,您可以使用它们,就像每个只包含您关心的符号一样。

如果您在单个 oct 文件中有多个函数定义,则使用 autoload()。因此,如果您有 foo.oct,它具有函数 foobar,那么您可以:

autoload ("bar", "path-to-foo.oct");

首先我要澄清您问题中的第二个引号-window。这不是特指 .oct 定义的函数。这意味着规范的 m 文件定义的函数与直接在控制台中或作为脚本的一部分定义的 'on-the-spot' 函数之间的区别。

至于第一个引用-window,当涉及到.oct文件中定义的函数时,情况就不同了。它的意思是您可以创建一个定义许多函数的 .oct 文件,但是为了 调用 这些函数,需要有一个 文件 在您的路径中使用相同的名称。因此,如果一个 .oct 文件定义了函数 "foo" 和 "bar",您需要有一份名为 "foo.oct" 的 .oct 文件的副本,以及另一个(或者更现实地说,作为符号 link改为原来的)改名为"bar.oct"。

同样,您也可以在您的工作区中定义一个 "foo.m" 和 "bar.m" 文件,其中仅包含这些功能的文档,这样如果您随后执行 "help foo" 或 "help bar" 你得到了预期的文档。

或者,您可以按照 carandraug 的建议使用 autoload

另一种生成 C 到 Octave 接口的可能性是在使用指针和数组时使用 SWIG which can generate a single .oct file with all your functions. Refer to here

这是一个例子:

header

/* File: example.h */

int fact(int n);

int fact2(int n1, int n2);

void add(int *x, int *y, int *r);

来源

/* File: example.c */

#include "example.h"

int fact(int n) {
    if (n < 0){ /* This should probably return an error, but this is simpler */
        return 0;
    }
    if (n == 0) {
        return 1;
    }
    else {
        /* testing for overflow would be a good idea here */
        return n * fact(n-1);
    }
}

int fact2(int n1, int n2) {
    return fact(n1)*fact(n2);
}

void add(int *x, int *y, int *r) {
    *r = *x + *y;
}

界面

/* File example.i */
%module swigexample
%include "cpointer.i"

%{
#include "example.h"
%}

%pointer_functions(int, intp)

%include "example.h"

编译

swig -octave -o swigexample.cpp example.i
mkoctfile -I. -I/usr/include/octave-4.2.2/ -Iswiglib swigexample.cpp example.c

测试

% File test.m
swigexample;
fact(5)
fact2(4,4)
% ==============
a = new_intp();
intp_assign(a, 37);
b = new_intp();
intp_assign(b, 22);
c = new_intp();
add(a,b,c);
r = intp_value(c);
delete_intp(a);
delete_intp(b);
delete_intp(c);
r