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

标签 delphi dll fortran

我有德尔福代码的问题。我想调用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';

您确实需要指定调用约定。您省略了这意味着您的代码使用了默认的 register Delphi 私有(private)的调用约定。我猜调用约定是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 确实非常容易。

关于delphi - 如何在delphi中从Fortran DLL调用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21017941/

相关文章:

optimization - 过度使用函数调用会影响性能吗?特别是在 Fortran 中

memory-management - 堆栈/堆内存模型是可选的吗?

fortran - 数组值数组索引

德尔菲减法错误?如何解决这个问题?

delphi - 我可以使用IdUDPClient发送M-SEARCH请求吗?

c++ - 如何设置.vcxproj以让MSBuild编译dll

c - 如何使用多种开发语言

C++ WINAPI 通过 GetProcAddress 调用导出函数

arrays - delphi字符串stringlist数组转换

delphi - 使用 Delphi 自动化 VideoLan 的 VLC