Recent

Author Topic: passing dynamic array as procedure argument?  (Read 16159 times)

acp693

  • Jr. Member
  • **
  • Posts: 73
passing dynamic array as procedure argument?
« on: July 01, 2009, 02:11:16 pm »
Hello,

I have the following code which calls a procedure in a dll( matrix multiplication) however I'm getting a SIGSEGV error message. If I change the dynamic arrays to static ones then it runs okay. Any ideas what I'm doing wrong?  Another question, does MyArray[2,3]  mean second column third row, or the other way round?  Many thanks.

Regards Albert

Code: [Select]
type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    StringGrid1: TStringGrid;
    procedure Button1Click(Sender: TObject);


  private
    { private declarations }
  public
    { public declarations }
  end;
  type tarray= array of array of double;



var
  Form1: TForm1;
  a,b,c: tarray;
  n:integer;
  procedure testblas31_MP_testdgemm(var a,b,c: tarray;var n:integer); cdecl; external 'testblas31.dll' ;


implementation

{ TForm1 }



procedure TForm1.Button1Click(Sender: TObject);
 var

 i,j:integer;

begin
     n:=2;
     setlength(a,n,n);
     setlength(b,n,n);
     setlength(c,n,n);
     a[0,0]:= 3.5;
     a[1,0]:= 2.4;
     a[0,1]:= 4.9;
     a[1,1]:= 6.7;

     b[0,0]:= 1.3;
     b[1,0]:= 8.9;
     b[0,1]:= 4.4;
     b[1,1]:= 3.5;

     for i:=0 to 1 do
     for j:=0 to 1 do
     c[i,j]:=0.0;

     testblas31_MP_testdgemm(a,b,c,n);

     for i:=0 to 1 do
     for j:=0 to 1 do
     stringgrid1.Cells[i,j] := floattostr(c[i,j]);


end;



initialization
  {$I unit1.lrs}

end.                                                               

Vincent Snijders

  • Administrator
  • Hero Member
  • *
  • Posts: 2661
    • My Lazarus wiki user page
Re: passing dynamic array as procedure argument?
« Reply #1 on: July 01, 2009, 03:52:47 pm »
You cannot pass dynamic arrays to non-pascal dlls, because they are managed types and @a is not the same as @a[0,0].

I would try the following:
Code: [Select]
procedure testblas31_MP_testdgemm(a,b,c: PDouble;var n:integer); cdecl; external 'testblas31.dll' ;

...
  testblas31_MP_testdgemm(@a[0,0],@b[0,0],@c[0,0],n);
...


Troodon

  • Sr. Member
  • ****
  • Posts: 484
Re: passing dynamic array as procedure argument?
« Reply #2 on: July 01, 2009, 05:29:02 pm »
http://www.delphibasics.co.uk/RTL.asp?Name=Array

"3.Open arrays
 
Both static and dynamic arrays may be passed to subroutines as parameters. If the array parameter definition has no range (ie, a dynamic array type), then you must, paradoxically pass a static array as a parameter. Such an array is referred to as an Open array. Delphi passes the length as a hidden parameter to the subroutine."
Lazarus/FPC on Linux

acp693

  • Jr. Member
  • **
  • Posts: 73
Re: passing dynamic array as procedure argument?
« Reply #3 on: July 01, 2009, 08:18:29 pm »
Thanks Vincent and Troodon,

Vincent, I tried the modifications you suggested, the program runs but the values returned in variable c are incorrect. the program also gives a SIGSEGV error message when closing. Any more ideas what I could try? It's more difficult than I thought it would be to connect external routines to Pascal!


regards Albert

Vincent Snijders

  • Administrator
  • Hero Member
  • *
  • Posts: 2661
    • My Lazarus wiki user page
Re: passing dynamic array as procedure argument?
« Reply #4 on: July 01, 2009, 08:57:17 pm »
Maybe you cannot use dynamic arrays in this case. Maybe the external code expects a contiguous block of memory, but the dynamic 2D array is actually a dynamic array of (dynamic arrays). So the external procedure overwrites some (meta)data of one the dynamic arrays and freeing the array cause awry.

If your n is actually fixed, then you can use static arrays (allocated on the heap if they are large). If you cannot use static arrays, you must use something like:
Code: [Select]
var
  a, b, c: PDouble;

begin
  a := getmem(n*n*sizeof(double));
  b := getmem(n*n*sizeof(double));
  c := getmem(n*n*sizeof(double));

   a[0]:= 3.5;
   a[n]:= 2.4;
   a[1]:= 4.9;
   a[n+1]:= 6.7;

...

    for i:=0 to 1 do
     for j:=0 to 1 do
       c[i*n+j]:=0.0;
 
  testblas31_MP_testdgemm(a,b,c,n);

end;

For the order of cells in the matrix, read http://en.wikipedia.org/wiki/Row-major_order

acp693

  • Jr. Member
  • **
  • Posts: 73
Re: passing dynamic array as procedure argument?
« Reply #5 on: July 01, 2009, 09:16:58 pm »
Thank you Vincent, that works. That's great. It's a shame the dynamic array approach didn't work though.  The cells ordering is different in Pascal than Fortran.

Regards Albert

Vincent Snijders

  • Administrator
  • Hero Member
  • *
  • Posts: 2661
    • My Lazarus wiki user page
Re: passing dynamic array as procedure argument?
« Reply #6 on: July 01, 2009, 09:24:59 pm »
The cell ordering is not the, but the fact that the memory of the array isn't one block, but n blocks.

 

TinyPortal © 2005-2018