Solved

C Multidimensional arrays and Delphi

Posted on 2004-10-27
550 Views
Last Modified: 2010-04-05
How can I pass a Delphi Multidimensional array to a C function that has the following declaration?

int Teste(int **v, int l, int c)

I know that Delphi and C have different Multidimensional arrays memory organizations. But I could not find any resource explaining clearly how can I bypass that.

Thanks
Mauricio.


0
Question by:MauricioMaia
    2 Comments
     
    LVL 26

    Assisted Solution

    by:Russell Libby
    Mauricio,

    The following will allow you to allocate a 2 dimensional integer array that can be passed to the C function. You didn't specifiy the number of dimensions, but looking at the Tests function, I made the assumtion that it was 2.

    // The declaration
    //
    // type declarator [<constant-expression>]
    //
    // declares an array composed of elements of type. An array consists of a
    // contiguous region of storage exactly large enough to hold all of its elements.
    // If an expression is given in an array declarator, it must evaluate to a
    // positive constant integer. The value is the number of elements in the
    // array. Each of the elements of an array is numbered from 0 through the
    // number of elements minus one.
    //
    // Multidimensional arrays are constructed by declaring arrays of array type.
    //

    type
      IntegerArray      =  Array [0..Pred(MaxInt shr 4)] of Integer;
      PIntegerArray     =  ^IntegerArray;
      TMDIntegerArray   =  Array [0..Pred(MaxInt shr 4)] of PIntegerArray;
      PMDIntegerArray   =  ^TMDIntegerArray;

    function CreateMDIntArray(Rows, Cols: Integer): PMDIntegerArray;
    var  dwIndex:    Integer;
    begin

      // We will allocate one more row than required (AND leave it null). This will
      // allow us to free the array without knowing the actual number of rows
      result:=AllocMem(Succ(Rows) * SizeOf(PIntegerArray));

      // Allocate memory for each row (except the last)
      for dwIndex:=0 to Pred(Rows) do result^[dwIndex]:=AllocMem(Cols * SizeOf(Integer));

    end;

    procedure FreeMDIntArray(MDIntArray: PMDIntegerArray);
    var  dwIndex:    Integer;
    begin

      // Set starting index
      dwIndex:=0;

      // Walk the rows until null is reached
      while Assigned(MDIntArray^[dwIndex]) do
      begin
         FreeMem(MDIntArray^[dwIndex]);
         Inc(dwIndex);
      end;

      // Free the array
      FreeMem(MDIntArray);

    end;

    var  pmdaTest:      PMDIntegerArray;
    begin

      // Create the multidimensional array
      pmdaTest:=CreateMDIntArray(10, 5);

      // Set [5, 0] to = 100
      pmdaTest^[5]^[0]:=100;

      // Pass the array to the teste function (used 5 and 0 for the other params, just for example)
      Teste(pmdaTest, 5, 0);

      // Free the array
      FreeMDIntArray(pmdaTest);

    end;

    ---

    Hope this helps,
    Russell


    0
     

    Accepted Solution

    by:
    Delphi

    Static array types
    A static array is stored as a contiguous sequence of variables of the component type of the array. The components with the lowest indexes are stored at the lowest memory addresses. A multidimensional array is stored with the rightmost dimension increasing first.
    (Ref: http://info.borland.com/techpubs/delphi/delphi5/oplg/memory.html)

    ANSI C (and C++ i believ)

    Multidimensional Arrays
    Multidimensional arrays are simply arrays of arrays (of arrays of arrays...)
    A multidimensional array like m[3][2] is stored in consecutive memory locations as m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1]

    So if you are using a Static interger array you should simply be able to pass the delphi array into the C function by typecasting the array to a pointer.

    NOTE: In C teh int **V is just a pointer to a memory location, which is the first integer in the array

    Here is some sample delphi code with a C like function i wrote to test this

    type
      INTARRAY = ^integer;   // int *
      PINTARRAY = ^INTARRAY; // int **

    // Test function to simulate a C style multidimesional integer array
    // int Teste(int **v, int l, int c)
    function Teste(v : PINTARRAY; cols : integer; rows : integer) : integer; stdcall;
    var
      idxC, idxR : integer;
      memAddr : integer;
      value : integer;
    begin
      for idxR := 0 to Rows - 1 do
        for idxC := 0 to Cols - 1 do
        begin
          //start + (y * width) + x;      width := sizeof(integer) * x)
          memAddr := integer(v) + (idxR * (sizeof(integer) * cols)) + (idxC * 4);
          value := INTARRAY(memAddr) ^;
          Form1.Memo1.Lines.Add(inttostr(value));
        end;

        result := 0;
    end;


    procedure TForm1.Button2Click(Sender: TObject);
    const
      COLCOUNT = 10;
      ROWCOUNT = 5;
    var
      col : integer;
      row : integer;
      aryDelphi : array[0..COLCOUNT - 1,0..ROWCOUNT - 1] of integer; // [cols, rows]
    begin

      //Fill in the array values
      for row := 0 to 4 do
      begin
        for col := 0 to 9 do
        begin
          aryDelphi[col][row] := (col * 5) + row;
        end;
      end;

      //I have assumed the Teste function will loop through the array using l and c
      // as the cols and orws value, in this case 10 columns by 5 rows
      Teste(@aryDelphi, COLCOUNT, ROWCOUNT);
    end;


    Hope it helps

    Richard Owen
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    IT, Stop Being Called Into Every Meeting

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
    Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
    Want to pick and choose which updates you receive? Feel free to check out this quick video on how to manage your email notifications.
    In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

    913 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    15 Experts available now in Live!

    Get 1:1 Help Now