| Thread overview | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
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 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alexandr Druzhinin | 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 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alexandr Druzhinin | 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 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to 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
| |||
August 08, 2012 Re: two-dimensional C array and its analog in D | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alexandr Druzhinin |
> 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 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alexandr Druzhinin | 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 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 :) | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply