将矩阵从MATLAB传递到FORTRAN dll时出错

时间:2012-02-08 20:54:49

标签: matlab dll fortran

我有一个简单的英特尔fortran dll编译如下:

function  add1(A,n)
!Expose  function  add1  to  users  of  this  DLL
!DEC$ ATTRIBUTES  C,DLLEXPORT:: add1
implicit none
double  precision  A(n,n),add1(n,n)
integer n
call add2(A,n)
A=A+1.0
add1=A
end  function  add1

subroutine add2(a,n)
double precision a(n,n)
integer n
a=a+1
endsubroutine

我还有一个dll的头文件:

double* add1(double*,int);

我使用MATLAB加载dll:

library='trydll.dll';
header='add1.h';
loadlibrary(library, header);
n=3;
haha=ones(n,n);
A=calllib('trydll','add1',haha,n)
unloadlibrary('trydll')

发送的矩阵和dll的整数严重错误,并且似乎是内存中的随机数。任何人都知道错误在哪里?

3 个答案:

答案 0 :(得分:1)

与巴伦建议一样,使用子程序让生活更轻松。让MATLAB分配内存。

以下是使用英特尔Fortran 12.1的完整工作示例:

subroutine CopyArray(A, B, n)

    !DEC$ ATTRIBUTES DLLEXPORT :: CopyArray
    !DEC$ ATTRIBUTES ALIAS: 'CopyArray' :: CopyArray
    !DEC$ ATTRIBUTES REFERENCE :: A, B
    !DEC$ ATTRIBUTES VALUE :: n

    real(8), intent(in),  dimension(n,n) :: A(n,n)
    real(8), intent(out), dimension(n,n) :: B(n,n)
    integer, intent(in) :: n

    B = A

end subroutine

标题文件:

void CopyArray(double*, double*, int);

MATLAB脚本:

n = 3;
A = rand(n, n);
B = zeros(n, n);

[A2, B2] = calllib(libname, 'CopyArray', A, B, n);

在这里使用libpointer似乎是可选的。看来MATLAB会自动将数组参数转换为指针。另请注意,引用(A,B)传递的参数将转换为MATLAB中的函数返回值。

答案 1 :(得分:0)

我目前无法对您的示例进行全面测试编码,但我可以从经验中说,我从来没有太多运气从Matlab以您的方式调用Fortran库。这是我的所作所为:

使用子程序代替函数。因此,将add1转换为更像:

SUBROUTINE add1(n,Ain,Aout)
  INTEGER, INTENT(in) :: n
  REAL*8, INTENT(in) :: Ain(n,n)
  REAL*8, INTENT(out) :: Aout(n,n)
  Aout = Ain + 1d0
END SUBROUTINE

然后从Matlab调用类似的东西:

n = 3;
Ain = ones(n,n);
Aout = libpointer('doublePtr',zeros(1,n));
calllib('trydll','add1',n,Ain,Aout);
Aout = Aout.value;

它可能只是你真正需要的最后.value部分,但我在这里没有记忆。

答案 2 :(得分:0)

我猜这是一个初始化问题。您可以在MATLAB中尝试以下脚本:

library='trydll.dll';
header='add1.h';
loadlibrary(library, header);
n=3;
arg_1 = libpointer('doublePtr',double(ones(1,n)))
arg_2 = libpointer('int32',n)
out_raw = libpointer('doublePtr') 
[output, arg_1] = calllib('trydll','add1',arg_1, arg_2)
unloadlibrary('trydll')

要查看FORTRAN / DLL输出:

out = get(out_raw,'Value')
for i=1:n
    display(out[i]);
end