Ошибка при передаче матриц из MATLAB в FORTRAN dll - PullRequest
1 голос
/ 09 февраля 2012

У меня есть простой intel 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 ]

1 голос
/ 21 августа 2012

Как предложил Баррон, используйте подпрограмму, чтобы облегчить жизнь.Пусть MATLAB выделяет память.

Вот полный рабочий пример использования Intel 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.

0 голосов
/ 20 сентября 2012

Полагаю, это проблема инициализации. Вы можете попробовать следующий скрипт в 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
0 голосов
/ 09 февраля 2012

В настоящее время я не могу написать ваш пример для тщательного тестирования, но по своему опыту могу сказать, что мне никогда не удавалось назвать библиотеки Фортрана из Matlab так, как вы показали. Вот что я делаю:

Используйте подпрограммы вместо функций. Итак, конвертируйте 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 часть, но у меня не хватает памяти здесь.

...