digitalmars.D - Passing static arrays to C
- Jakob Bornecrantz (33/33) Oct 24 2012 Hey everybody.
- Jacob Carlborg (12/40) Oct 24 2012 That seems weird. Since static arrays are passed by value in D you need
- Jakob Bornecrantz (6/56) Oct 24 2012 Yeah I'm wondering if this isn't a bug.
- Walter Bright (3/45) Oct 24 2012 In D, static arrays are passed by value, in C by pointer. Hence, you hav...
- bearophile (7/10) Oct 24 2012 Isn't it possible to help the programmer avoid some similar
- Andrej Mitrovic (2/6) Oct 24 2012 Agreed. File to bugzilla unless Walter disagrees?
- Andrej Mitrovic (2/3) Oct 24 2012 Also, what should the error message look like? I've got a pull in works ...
- Andrej Mitrovic (10/14) Oct 24 2012 Small test-case:
- bearophile (9/10) Oct 24 2012 Andrej Mitrovic:
- Andrej Mitrovic (4/11) Oct 24 2012 Well this is less dangerous than the OP case, but maybe it should be
- Walter Bright (3/4) Oct 24 2012 C accepts static arrays as pointers, so T[n] in D would be C prototyped ...
- Era Scarecrow (8/11) Oct 24 2012 In GCC (or any c compiler) isn't it possible in optimizing to
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (8/18) Oct 24 2012 Passing static arrays by reference to the first element is part of the
Hey everybody. How are you supposed to pass static arrays to C functions? I'm asking because I'm getting conflicting info from how DMD works and on IRC. The below example prints: test1 0x7fff857c1db0 test2 0x7fff857c1db0 test3 (nil) test4 0x7fff857c1db0 D: void main() { float[3] arr; test1(arr); test2(&arr[0]); test3(0, arr); test4(0, &arr[0]); } extern(C): void test1(float[3] arr); void test2(float *arr); void test3(int, float[3] arr); void test4(int, float *arr); C: #include <stdio.h> void test1(float arr[3]) { printf("test1 %p\n", &arr[0]); } void test2(float arr[3]) { printf("test2 %p\n", &arr[0]); } void test3(int anything, float arr[3]) { printf("test3 %p\n", &arr[0]); } void test4(int anything, float arr[3]) { printf("test4 %p\n", &arr[0]); } Comments please. Cheers, Jakob.
Oct 24 2012
On 2012-10-24 09:54, Jakob Bornecrantz wrote:Hey everybody. How are you supposed to pass static arrays to C functions? I'm asking because I'm getting conflicting info from how DMD works and on IRC. The below example prints: test1 0x7fff857c1db0 test2 0x7fff857c1db0 test3 (nil) test4 0x7fff857c1db0 D: void main() { float[3] arr; test1(arr); test2(&arr[0]); test3(0, arr); test4(0, &arr[0]); } extern(C): void test1(float[3] arr); void test2(float *arr); void test3(int, float[3] arr); void test4(int, float *arr); C: #include <stdio.h> void test1(float arr[3]) { printf("test1 %p\n", &arr[0]); } void test2(float arr[3]) { printf("test2 %p\n", &arr[0]); } void test3(int anything, float arr[3]) { printf("test3 %p\n", &arr[0]); } void test4(int anything, float arr[3]) { printf("test4 %p\n", &arr[0]); }That seems weird. Since static arrays are passed by value in D you need to send a reference: extern (C) void test1(ref float[3] arr); float[3] arr; test1(arr); BTW, do not ever use "&arr[0]", use "arr.ptr" instead to get the pointer of the array. http://dlang.org/interfaceToC.html Search for "Passing D Array Arguments to C Functions". -- /Jacob Carlborg
Oct 24 2012
On Wednesday, 24 October 2012 at 09:03:25 UTC, Jacob Carlborg wrote:On 2012-10-24 09:54, Jakob Bornecrantz wrote:Yeah I'm wondering if this isn't a bug.Hey everybody. How are you supposed to pass static arrays to C functions? I'm asking because I'm getting conflicting info from how DMD works and on IRC. The below example prints: test1 0x7fff857c1db0 test2 0x7fff857c1db0 test3 (nil) test4 0x7fff857c1db0 D: void main() { float[3] arr; test1(arr); test2(&arr[0]); test3(0, arr); test4(0, &arr[0]); } extern(C): void test1(float[3] arr); void test2(float *arr); void test3(int, float[3] arr); void test4(int, float *arr); C: #include <stdio.h> void test1(float arr[3]) { printf("test1 %p\n", &arr[0]); } void test2(float arr[3]) { printf("test2 %p\n", &arr[0]); } void test3(int anything, float arr[3]) { printf("test3 %p\n", &arr[0]); } void test4(int anything, float arr[3]) { printf("test4 %p\n", &arr[0]); }That seems weird. Since static arrays are passed by value in D you need to send a reference:extern (C) void test1(ref float[3] arr); float[3] arr; test1(arr); BTW, do not ever use "&arr[0]", use "arr.ptr" instead to get the pointer of the array.Right you are, thats what you get when mixing C and D code.http://dlang.org/interfaceToC.html Search for "Passing D Array Arguments to C Functions".Thanks for the info. Cheers, Jakob.
Oct 24 2012
On 10/24/2012 2:55 AM, Jakob Bornecrantz wrote:On Wednesday, 24 October 2012 at 09:03:25 UTC, Jacob Carlborg wrote:In D, static arrays are passed by value, in C by pointer. Hence, you have a mismatch between the C and D prototypes of test1, and you'll get garbage results.On 2012-10-24 09:54, Jakob Bornecrantz wrote:Yeah I'm wondering if this isn't a bug.Hey everybody. How are you supposed to pass static arrays to C functions? I'm asking because I'm getting conflicting info from how DMD works and on IRC. The below example prints: test1 0x7fff857c1db0 test2 0x7fff857c1db0 test3 (nil) test4 0x7fff857c1db0 D: void main() { float[3] arr; test1(arr); test2(&arr[0]); test3(0, arr); test4(0, &arr[0]); } extern(C): void test1(float[3] arr); void test2(float *arr); void test3(int, float[3] arr); void test4(int, float *arr); C: #include <stdio.h> void test1(float arr[3]) { printf("test1 %p\n", &arr[0]); } void test2(float arr[3]) { printf("test2 %p\n", &arr[0]); } void test3(int anything, float arr[3]) { printf("test3 %p\n", &arr[0]); } void test4(int anything, float arr[3]) { printf("test4 %p\n", &arr[0]); }That seems weird. Since static arrays are passed by value in D you need to send a reference:
Oct 24 2012
Walter Bright:In D, static arrays are passed by value, in C by pointer. Hence, you have a mismatch between the C and D prototypes of test1, and you'll get garbage results.Isn't it possible to help the programmer avoid some similar mistakes with some warnings or errors? I think the extern(C) annotation, plus the function signatures, give the D compiler all the info it needs. Bye, bearophile
Oct 24 2012
On 10/24/12, bearophile <bearophileHUGS lycos.com> wrote:Isn't it possible to help the programmer avoid some similar mistakes with some warnings or errors? I think the extern(C) annotation, plus the function signatures, give the D compiler all the info it needs.Agreed. File to bugzilla unless Walter disagrees?
Oct 24 2012
On 10/24/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Agreed. File to bugzilla unless Walter disagrees?Also, what should the error message look like? I've got a pull in works fwiw.
Oct 24 2012
On 10/24/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:On 10/24/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Small test-case: extern(C) void fail(int[4] x); extern(C) int[4] fail2(); extern(C) void c_ok1(ref int[4] x); extern(C) void c_ok2(out int[4] x); extern(C) void c_ok3(int[4]* x); extern(C) ref int[4] c_ok4(); extern(C) int[4]* c_ok5(); Have I covered everything?Agreed. File to bugzilla unless Walter disagrees?Also, what should the error message look like? I've got a pull in works fwiw.
Oct 24 2012
Andrej Mitrovic: The issue you have opened is: http://d.puremagic.com/issues/show_bug.cgi?id=8887Have I covered everything?The implementation of D associative arrays is opaque, so why is this allowed? extern(C) void foo(int[int] aa); void main() {} Bye, bearophile
Oct 24 2012
On 10/24/12, bearophile <bearophileHUGS lycos.com> wrote:Andrej Mitrovic: The issue you have opened is: http://d.puremagic.com/issues/show_bug.cgi?id=8887And pull https://github.com/D-Programming-Language/dmd/pull/1215The implementation of D associative arrays is opaque, so why is this allowed? extern(C) void foo(int[int] aa); void main() {}Well this is less dangerous than the OP case, but maybe it should be disallowed. Another bug should be opened for this.
Oct 24 2012
On 10/24/2012 12:54 AM, Jakob Bornecrantz wrote:How are you supposed to pass static arrays to C functions?C accepts static arrays as pointers, so T[n] in D would be C prototyped as T*. Pass a pointer to the first element.
Oct 24 2012
On Wednesday, 24 October 2012 at 09:16:30 UTC, Walter Bright wrote:C accepts static arrays as pointers, so T[n] in D would be C prototyped as T*. Pass a pointer to the first element.In GCC (or any c compiler) isn't it possible in optimizing to copy the static array to the stack (say 8 bytes or less as a guess)? Course this assumes the static size is set as part of the function signature too... It makes sense for it to work both ways (in their own way); But then more bugs can lie in wait as well.
Oct 24 2012
On 24-10-2012 12:00, Era Scarecrow wrote:On Wednesday, 24 October 2012 at 09:16:30 UTC, Walter Bright wrote:Passing static arrays by reference to the first element is part of the calling convention/ABI. If the C compiler generated code that doesn't work this way, the C compiler has a bug. -- Alex Rønne Petersen alex lycus.org http://lycus.orgC accepts static arrays as pointers, so T[n] in D would be C prototyped as T*. Pass a pointer to the first element.In GCC (or any c compiler) isn't it possible in optimizing to copy the static array to the stack (say 8 bytes or less as a guess)? Course this assumes the static size is set as part of the function signature too... It makes sense for it to work both ways (in their own way); But then more bugs can lie in wait as well.
Oct 24 2012