Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在delphi中从Fortran DLL调用函数?_Delphi_Dll_Fortran - Fatal编程技术网

如何在delphi中从Fortran DLL调用函数?

如何在delphi中从Fortran DLL调用函数?,delphi,dll,fortran,Delphi,Dll,Fortran,我对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 suf

我对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;

我无法调用函数(粗体)。

我会这样声明函数:

procedure c_zsn(
  m: Double;
  d: Double;
  k: double; 
  f: PDouble; 
  zsn: PDouble;
  n: Integer
); stdcall; external 'dllsub.dll';
c_zsn(e,d,f,@l[0],@o[0],n);
var
  l, o: array [0..9] of Double;
您确实需要指定调用约定。您忽略了这一点,这意味着您的代码使用了默认的
寄存器
调用约定,该约定是Delphi专用的。我猜调用约定是
stdcall
,但它可能是
cdecl
。检查编译器文档以确保正确

我一点也不明白为什么你声明了一个返回双精度的函数。Fortran不能做到这一点

除此之外,我更改了参数名称以匹配Fortran代码。我还切换到加载时间链接,这更容易编码。您可以跳过对
LoadLibrary
GetProcAddress
的调用,让加载程序解析链接

最后,我认为这两个数组最好作为
PDouble
(即指向
Double
)传递,而不是在编译时提交到固定大小的数组

您可以这样调用函数:

procedure c_zsn(
  m: Double;
  d: Double;
  k: double; 
  f: PDouble; 
  zsn: PDouble;
  n: Integer
); stdcall; external 'dllsub.dll';
c_zsn(e,d,f,@l[0],@o[0],n);
var
  l, o: array [0..9] of Double;
请注意,您已经声明了长度为11而不是10的数组。你是有意的吗?我认为您应该这样声明数组:

procedure c_zsn(
  m: Double;
  d: Double;
  k: double; 
  f: PDouble; 
  zsn: PDouble;
  n: Integer
); stdcall; external 'dllsub.dll';
c_zsn(e,d,f,@l[0],@o[0],n);
var
  l, o: array [0..9] of Double;

最后一点是Fortran代码非常简单。把它翻译成Delphi确实很容易

C是DLL的“通用语言”。我认为有很多教程可以为您的Fortran文件制作C头文件(*.h)。还有很多教程介绍如何将C头翻译成Pascal。@Arioch'无需将接口转换成C。@DavidHeffernan当然,直接翻译总是比使用中间语言“通用语”效果更好。但后者有时是“足够好”的,而且有更多的产品:-)这只是一个“分而治之”的例子sense@fcn:=GetProcAddress(a,'c_zsn'),但是否测试@b=nil???