我有一个简单的英特尔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的整数严重错误,并且似乎是内存中的随机数。任何人都知道错误在哪里?
答案 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