Jump to page: 1 2
Thread overview
Passing static arrays to C
Oct 24, 2012
Jakob Bornecrantz
Oct 24, 2012
Jacob Carlborg
Oct 24, 2012
Jakob Bornecrantz
Oct 24, 2012
Walter Bright
Oct 24, 2012
bearophile
Oct 24, 2012
Andrej Mitrovic
Oct 24, 2012
Andrej Mitrovic
Oct 24, 2012
Andrej Mitrovic
Oct 24, 2012
bearophile
Oct 24, 2012
Andrej Mitrovic
Oct 24, 2012
Walter Bright
Oct 24, 2012
Era Scarecrow
October 24, 2012
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.


October 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
October 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.

October 24, 2012
On Wednesday, 24 October 2012 at 09:03:25 UTC, Jacob Carlborg wrote:
> 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:

Yeah I'm wondering if this isn't a bug.

>
> 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.


October 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.
October 24, 2012
On 24-10-2012 12:00, Era Scarecrow wrote:
> 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.

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.org
October 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:
>> 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:
>
> Yeah I'm wondering if this isn't a bug.

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.

October 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
October 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?
October 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.
« First   ‹ Prev
1 2