显然,您的特定用例可能比这复杂得多,但这里有一个简单的示例来帮助您入门(或帮助您决定是否值得走这条路......)
让我们从一个简单的 octfile 开始,它执行简单的整数加法,目前不涉及 Fortran。
// in: simple_addition.cpp
#include <octave/oct.h>
DEFUN_DLD (simple_addition, args, ,"Add two integers via C++")
{
octave_value retval = args(0).int_value() + args(1).int_value();
return retval;
}
Compile:
mkoctfile -c simple_addition.cpp # compiles a simple_addition.o file
mkoctfile -o simple_addition simple_addition.o # links .o file to named output file
以八度为单位:
octave:1> simple_addition(1,2)
ans = 3
现在让我们先把这个放在一边,看看如何从纯 C++ 调用 Fortran 定义的函数。首先让我们创建一个简单的整数加法函数:
! in fortran_addition.f90
function fortran_addition(a,b) result(Out)
integer, intent(in) :: a,b ! input
integer :: Out ! output
Out = a + b
end function fortran_addition
并使用 gfortran 编译它:
gfortran -c fortran_addition.f90 # creates fortran_addition.o
你可以看到(例如使用nm fortran_addition.o
)生成的对象包含对该名称下的符号的引用fortran_addition_
(注意最后添加的下划线)。
现在让我们创建一个普通的(即非八度相关的)C++ 包装程序,它调用通过此符号定义的函数:
// in generic_fortran_addition_wrapper.cpp
#include <iostream>
extern "C" { int fortran_addition_( int *, int * ); }
int main() {
int a = 1, b = 2, fortran_result;
fortran_result = fortran_addition_( &a, &b );
std::cout << a << " + " << b << " = " << fortran_result << std::endl;
}
compile:
g++ -c generic_fortran_addition_wrapper.cpp
g++ -o addints generic_fortran_addition_wrapper.o fortran_addition.o
./addints # outputs `1 + 2 = 3` on the terminal
现在我们拥有了创建包装 fortran 函数的 octfile 的所有要素:
// in fortran_addition_wrapper.cpp
#include <octave/oct.h>
extern "C" { int fortran_addition_( int *, int *); }
DEFUN_DLD (fortran_addition_wrapper, args, ,"Add two integers via fortran")
{
int a, b, fortran_result;
a = args(0).int_value();
b = args(1).int_value();
fortran_result = fortran_addition_( &a, &b );
octave_value retval(fortran_result);
return retval;
}
使用 mkoctfile 编译:
mkoctfile -c fortran_addition_wrapper.cpp
mkoctfile -o fortran_addition_wrapper fortran_addition_wrapper.o fortran_addition.o
然后八度:
octave:1> fortran_addition_wrapper(1,2)
ans = 3
话虽如此,显然如果您有一个完全定义的 fortran 程序,而不仅仅是可链接函数,并且您的系统上有一个正在运行的已编译可执行文件,那么您可以跳过所有上述“手续”,只需通过system()
来自八度的命令。显然,在这种情况下,您需要以与八度音程无关的方式传递数据……但如果您有一个独立的 fortran 可执行文件,那么它可能已经有一种从操作系统读取输入数据的方法。
EDIT根据下面的评论,有人提醒我,我偏离了方向,回答了原始问题的评论中提出的问题,却忘记解决原始问题中的错误消息。正如我在评论中提到的,mkoctave 是 gnu 编译器集合的通用包装器。这些消息听起来并不是特定于 Octave,而是编译器/链接器抱怨您缺少定义这些基本函数的 Fortran 运行时库。