View mode: basic / threaded / horizontal-split · Log in · Help
August 08, 2012
two-dimensional C array and its analog in D
Hello,
there is the following C function:

void foo(const void** data);

in C I can do:

int data[N][M];

data[0][0] = ..;
data[0][1] = ..;
data[1][0] = ..;
data[1][1] = ..;

foo(data); // for C code it works and in D code it doesn't (compile, but 
do nothing)

I've "solved" the problem like this:

int real_data[N*M];

real_data[0] = ..;
real_data[1] = ..;
real_data[2] = ..;
real_data[3] = ..;

int* data[N];
foreach(i; 0..N)
	data[i] = &real_data[i*M];

T.i. I form an array of pointers by myself without compiler so it 
doesn't seem to be good enough for some overcode and it looks dirty a 
little bit. Is there more suitable variant?

P.S. in few words I'd like to construct some D data structure that is 
binary compatible with two-dimensional C array (and do it in simple way, 
of course).
August 08, 2012
Re: two-dimensional C array and its analog in D
On 08/07/2012 11:07 PM, Alexandr Druzhinin wrote:
> Hello,
> there is the following C function:
>
> void foo(const void** data);
>
> in C I can do:
>
> int data[N][M];
>
> data[0][0] = ..;
> data[0][1] = ..;
> data[1][0] = ..;
> data[1][1] = ..;
>
> foo(data); // for C code it works and in D code it doesn't (compile, but
> do nothing)

This seems to work:

import std.stdio;

void main()
{
    enum M = 3;
    enum N = 4;

    int[M][N] data;
    data[0][0] = 42;
    writeln(data);
}

The output:

[[42, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

Ali
August 08, 2012
Re: two-dimensional C array and its analog in D
Alexandr Druzhinin:

> there is the following C function:
>
> void foo(const void** data);
>
> in C I can do:
>
> int data[N][M];
>
> data[0][0] = ..;
> data[0][1] = ..;
> data[1][0] = ..;
> data[1][1] = ..;
>
> foo(data); // for C code it works and in D code it doesn't 
> (compile, but do nothing)

That C code doesn't look correct, because the given data contains
no pointers.

Why don't you show us a complete compilable runnable correct tiny
C program, that we have to translate to D?

Bye,
bearophile
August 08, 2012
Re: two-dimensional C array and its analog in D
> That C code doesn't look correct, because the given data 
> contains no pointers.

But this C code compiles:


void foo(const void** data) {}
int data[2][3];
int main() {
  foo(data);
  return 0;
}

Bye,
bearophile
August 08, 2012
Re: two-dimensional C array and its analog in D
08.08.2012 16:29, bearophile пишет:
>> That C code doesn't look correct, because the given data contains no
>> pointers.
>
> But this C code compiles:
>
>
> void foo(const void** data) {}
> int data[2][3];
> int main() {
>    foo(data);
>    return 0;
> }
>
> Bye,
> bearophile

As I know in C an array is equal to pointer, so array of array == array 
of pointers == pointer to pointer == pointer to array. Correct me if I'm 
wrong.

I'm trying to use OpenGL function glMultiDrawElements. It has signature:
void glMultiDrawElements(
  enum mode,
  sizei *count,
  enum type,
  void **indices,
  sizei primcount
);
If I declare indices like
uint[][] indices;
then code compiles but doesn't work (but it works in C). If I do as I 
described in the first post - it works in D. And I'd like to understand 
the reason of it. I think the reason is difference tween C array and D 
array, but I'm not sure.

p.s. example of real code is too large to paste
August 08, 2012
Re: two-dimensional C array and its analog in D
08.08.2012 12:13, Ali Çehreli пишет:
>
> This seems to work:
>
> import std.stdio;
>
> void main()
> {
>      enum M = 3;
>      enum N = 4;
>
>      int[M][N] data;
>      data[0][0] = 42;
>      writeln(data);
> }
>
> The output:
>
> [[42, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>
> Ali
>

I mean that I call C function from D code. And C function takes void** 
pointer as its argument. In C this means array of array, but if I pass D 
two-dimensional array it doesn't work (but compiles).
August 08, 2012
Re: two-dimensional C array and its analog in D
> I mean that I call C function from D code. And C function takes 
> void** pointer as its argument. In C this means array of array, 
> but if I pass D two-dimensional array it doesn't work (but 
> compiles).

I'm pretty sure that the issue is D's internal implementation of 
2-dimensional arrays. From what I remember, if the arrays are 
defined as fixed-size, D creates just a single block of array 
data rather than creating pointers to pointers. OpenGL is 
expecting an array of pointers to 1-dimensional arrays, but D is 
giving it the pointer to the actual indices.
August 08, 2012
Re: two-dimensional C array and its analog in D
On 08/08/2012 07:12 AM, Alexandr Druzhinin wrote:
> 08.08.2012 16:29, bearophile пишет:
>>> That C code doesn't look correct, because the given data contains no
>>> pointers.
>>
>> But this C code compiles:
>>
>>
>> void foo(const void** data) {}
>> int data[2][3];
>> int main() {
>> foo(data);
>> return 0;
>> }

gcc does not accept that code:

deneme.c:18920: error: passing argument 1 of ‘foo’ from incompatible 
pointer type
deneme.c:18914: note: expected ‘const void **’ but argument is of type 
‘int (*)[3]’

> As I know in C an array is equal to pointer,

In C and C++, an Array is automatically converted to a pointer to its 
first element.

> so array of array == array
> of pointers == pointer to pointer == pointer to array. Correct me if I'm
> wrong.
>
> I'm trying to use OpenGL function glMultiDrawElements. It has signature:
> void glMultiDrawElements(
> enum mode,
> sizei *count,
> enum type,
> void **indices,
> sizei primcount
> );

I looked at its online documentation: count is also an array that tells 
the lengths of individual rows of indices, right? So in reality the data 
is a dynamic ragged array? (I've never used that function before.)

> If I declare indices like
> uint[][] indices;

That's a slice of uint slices. Completely different memory layout than 
static arrays.

In any case, I am pretty sure that what you need is the .ptr property of 
D arrays. You will have to make the 'indices' parameter dynamically by 
calling .ptr on the slices.

> then code compiles but doesn't work (but it works in C). If I do as I
> described in the first post - it works in D. And I'd like to understand
> the reason of it. I think the reason is difference tween C array and D
> array, but I'm not sure.
>
> p.s. example of real code is too large to paste

I've started writing the following but I don't know how you are calling 
the function. Can you get this to do what you expect in C:

// WARNING: THIS C CODE DOES NOT COMPILE.
#include <stdio.h>

typedef size_t sizei;

void glMultiDrawElements(
    /* enum mode,*/
    sizei *count,
    /* enum type,*/
    void **indices,
    sizei primcount)
{
    for (size_t i = 0; i != primcount; ++i) {
        for (size_t j = 0; j != count[i]; ++j) {
            printf(" %d", indices[i][j]);
        }
        printf("\n");
    }
}

int main()
{
    /* Normally, the count array would be generated dynamically. */
    int counts[4] = { 3, 3, 3, 3 };

    int data[4][3];
    data[0][0] = 42;
    data[2][2] = 43;

    glMultiDrawElements(counts, data, 4);
}

Ali

-- 
D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
August 08, 2012
Re: two-dimensional C array and its analog in D
08.08.2012 22:21, Ali Çehreli пишет:
>
> I looked at its online documentation: count is also an array that tells
> the lengths of individual rows of indices, right? So in reality the data
> is a dynamic ragged array? (I've never used that function before.)

Yes, it is.

>
>  > If I declare indices like
>  > uint[][] indices;
>
> That's a slice of uint slices. Completely different memory layout than
> static arrays.

Ok. I'll read about slices once again

> In any case, I am pretty sure that what you need is the .ptr property of
> D arrays. You will have to make the 'indices' parameter dynamically by
> calling .ptr on the slices.

.ptr works fine. if I do, for example so:

uint[] firstSubArray;
uint[] secondSubArray;

uint*[] indicies;
indicies[0] = firstSubArray.ptr;
indicies[1] = secondSubArray.ptr;

that is I manually form array of pointers. But I don't like it.

>
> I've started writing the following but I don't know how you are calling
> the function. Can you get this to do what you expect in C:
>
> // WARNING: THIS C CODE DOES NOT COMPILE.
> #include <stdio.h>
>
> typedef size_t sizei;
>
> void glMultiDrawElements(
>      /* enum mode,*/
>      sizei *count,
>      /* enum type,*/
>      void **indices,
>      sizei primcount)
> {
>      for (size_t i = 0; i != primcount; ++i) {
>          for (size_t j = 0; j != count[i]; ++j) {
>              printf(" %d", indices[i][j]);
>          }
>          printf("\n");
>      }
> }
>
> int main()
> {
>      /* Normally, the count array would be generated dynamically. */
>      int counts[4] = { 3, 3, 3, 3 };
>
>      int data[4][3];
>      data[0][0] = 42;
>      data[2][2] = 43;
>
>      glMultiDrawElements(counts, data, 4);
> }

yes, it looks like what I mean, but I'm sleepy now :)
Top | Discussion index | About this forum | D home