digitalmars.D.learn - two-dimensional C array and its analog in D
- Alexandr Druzhinin (26/26) Aug 07 2012 Hello,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (14/25) Aug 07 2012 This seems to work:
- Alexandr Druzhinin (4/17) Aug 08 2012 I mean that I call C function from D code. And C function takes void**
- BLM768 (6/10) Aug 08 2012 I'm pretty sure that the issue is D's internal implementation of
- bearophile (7/17) Aug 08 2012 That C code doesn't look correct, because the given data contains
- bearophile (9/11) Aug 08 2012 But this C code compiles:
- Alexandr Druzhinin (19/30) Aug 08 2012 As I know in C an array is equal to pointer, so array of array == array
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (47/79) Aug 08 2012 gcc does not accept that code:
- Alexandr Druzhinin (11/49) Aug 08 2012 Ok. I'll read about slices once again
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).
Aug 07 2012
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
Aug 07 2012
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]] AliI 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).
Aug 08 2012
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.
Aug 08 2012
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
Aug 08 2012
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
Aug 08 2012
08.08.2012 16:29, 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 pasteThat 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
Aug 08 2012
On 08/08/2012 07:12 AM, Alexandr Druzhinin wrote:08.08.2012 16:29, bearophile пишет: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]’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; }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 pasteI'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
Aug 08 2012
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 againIn 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 :)
Aug 08 2012