从单个 *.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 的用途——你有符号 A
、B
和 C
吗?使 A.oct
、B.oct
和 C.oct
符号化 link 指向该文件,您可以使用它们,就像每个只包含您关心的符号一样。
如果您在单个 oct 文件中有多个函数定义,则使用 autoload()
。因此,如果您有 foo.oct
,它具有函数 foo
和 bar
,那么您可以:
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
我有一个 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 的用途——你有符号 A
、B
和 C
吗?使 A.oct
、B.oct
和 C.oct
符号化 link 指向该文件,您可以使用它们,就像每个只包含您关心的符号一样。
如果您在单个 oct 文件中有多个函数定义,则使用 autoload()
。因此,如果您有 foo.oct
,它具有函数 foo
和 bar
,那么您可以:
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