我的delphi代码有问题。我想在delphi中调用函数来处理fortran函数,但我已经转移到了DLL。这是代码Fortran
SUBROUTINE c_zsn(m,d,k,f,zsn,nf)
! Specify that the routine name is to be made available to callers of the
! DLL and that the external name should not have any prefix or suffix
!MS$ ATTRIBUTES DLLEXPORT :: c_zsn
!MS$ ATTRIBUTES ALIAS:'c_zsn' :: c_zsn
!MS$ ATTRIBUTES VALUE :: m,d,k,nf
!MS$ ATTRIBUTES REFERENCE :: f,zsn
IMPLICIT NONE
INTEGER :: nf,i
REAL(KIND(0.D0)) :: m,d,k,f(0:(nf-1)),zsn(0:(nf-1)),om,pi
COMPLEX(KIND(0.D0)) :: j
j = (0.d0, 1.d0)
pi = 4.d0 * datan(1.d0)
do i=0,nf-1
om = 2.d0*pi*f(i)
zsn(i) = abs(-om**2*m-j*om*d+k)
end do
END SUBROUTINE
这是我用过的Delphi的代码
procedure TForm1.Button2Click(Sender: TObject);
type tarray=array[0..10]of double;
var a:thandle;
fcn:function(s,d,f:double;var g,h:tarray;n:integer):double;
e,f,d,g,h,i,j:double;
k:tarray;
l,o:tarray;
n,m:integer;
begin
a:=LoadLibrary('dllsub.dll');
if (A=0) then
begin
Application.MessageBox('Failed to open library','Error', MB_OK or MB_ICONEXCLAMATION);
exit;
end;
@fcn:=GetProcAddress(a, 'c_zsn');
if @b=nil then
begin
ShowMessage('Failed to open function');
exit;
end;
e:=2;
f:=200;
d:=0.01;
n:=10;
for m:=0 to n do
l[m]:=m;
fcn(e,d,f,l,o,n); // this is the problem
FreeLibrary(a);
end;
我无法调用该函数(粗体)。
答案 0 :(得分:1)
我会声明这样的函数:
procedure c_zsn(
m: Double;
d: Double;
k: double;
f: PDouble;
zsn: PDouble;
n: Integer
); stdcall; external 'dllsub.dll';
您需要指定调用约定。您省略了这意味着您的代码使用了Delphi私有的默认register
调用约定。我猜测调用约定是stdcall
但它可能是cdecl
。检查编译器文档以确定。
对我来说,为什么你声明一个返回double的函数并不是很明显。 Fortran不这样做。
除此之外,我更改了参数名称以匹配Fortran代码。我还切换到加载时间链接,这更容易编码。您可以跳过对LoadLibrary
和GetProcAddress
的调用,让加载程序解析链接。
最后,我认为两个数组最好传递为PDouble
(指向Double
的指针),而不是在编译时提交给固定大小的数组。
你可以这样调用这个函数:
c_zsn(e,d,f,@l[0],@o[0],n);
请注意,您已声明长度为11而不是长度为10的数组。您的意思是这样吗?我认为你应该声明这样的数组:
var
l, o: array [0..9] of Double;
最后一点是Fortran代码非常简单。将它翻译成Delphi非常容易。