Thread overview | ||||||
---|---|---|---|---|---|---|
|
December 08, 2009 static arrays in C functions | ||||
---|---|---|---|---|
| ||||
Since a while some extern(C) functions which take arrays seem to be broken. Can anybody clarify /confirm how they should be declared? For example I stumbled upon this: import core.sys.posix.unistd, std.stdio; void main() { int[2] fd; writeln( pipe(fd) ); // failes with errno == EFAULT } In core.sys.posix.unistd, pipe is declared as: int pipe(int[2]); This works though: extern (C) { int pipe(int*); } void main() { int[2] fd; writeln( pipe(fd.ptr) ); } |
December 08, 2009 Re: static arrays in C functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lutger | On Tue, Dec 8, 2009 at 2:08 AM, Lutger <lutger.blijdestijn@gmail.com> wrote:
> Since a while some extern(C) functions which take arrays seem to be broken. Can anybody clarify /confirm how they should be declared?
>
> For example I stumbled upon this:
>
> import core.sys.posix.unistd, std.stdio;
>
> void main()
> {
> int[2] fd;
> writeln( pipe(fd) ); // failes with errno == EFAULT
> }
>
> In core.sys.posix.unistd, pipe is declared as: int pipe(int[2]);
>
>
> This works though:
>
> extern (C) { int pipe(int*); }
>
> void main()
> {
> int[2] fd;
> writeln( pipe(fd.ptr) );
> }
(Assuming you're talking about D2 here...)
A few releases ago fixed-size arrays changed to be pass-by-value.
But I guess there's still some logic in there to interpret int[2] as
int* when inside an extern(C) block.
It does seem like there's a bug there, though. I think pipe(fd) in the first case should fail to compile because it's attempting to pass by value where a pointer is expected.
--bb
|
December 08, 2009 Re: static arrays in C functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | On Tue, 08 Dec 2009 11:53:12 -0500, Bill Baxter <wbaxter@gmail.com> wrote: > On Tue, Dec 8, 2009 at 2:08 AM, Lutger <lutger.blijdestijn@gmail.com> wrote: >> Since a while some extern(C) functions which take arrays seem to be broken. >> Can anybody clarify /confirm how they should be declared? >> >> For example I stumbled upon this: >> >> import core.sys.posix.unistd, std.stdio; >> >> void main() >> { >> int[2] fd; >> writeln( pipe(fd) ); // failes with errno == EFAULT >> } >> >> In core.sys.posix.unistd, pipe is declared as: int pipe(int[2]); >> >> >> This works though: >> >> extern (C) { int pipe(int*); } >> >> void main() >> { >> int[2] fd; >> writeln( pipe(fd.ptr) ); >> } > > (Assuming you're talking about D2 here...) > A few releases ago fixed-size arrays changed to be pass-by-value. > But I guess there's still some logic in there to interpret int[2] as > int* when inside an extern(C) block. No it compiles *because* that logic is not there. It now thinks int[2] is a pass-by-value entity. It links because you are using C linkage which does not do name-mangling. I could define pipe as: extern (C) int pipe(char c, int x, float y); and it will still link :) > It does seem like there's a bug there, though. I think pipe(fd) in > the first case should fail to compile because it's attempting to pass > by value where a pointer is expected. The error is either: a) you now need to declare C functions that were declared in C taking an array to taking a pointer, so core.sys.posix.unistd (and likely others) needs to be fixed. b) as you suggested, inside a C block, int[2] should be interpreted as int *. I'd prefer a, because I don't care much about direct translation of C headers :) If b is chosen as a solution, I'd also like to have the compiler automatically pass the pointer when calling a C function. -Steve |
December 08, 2009 Re: static arrays in C functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer wrote: > On Tue, 08 Dec 2009 11:53:12 -0500, Bill Baxter <wbaxter@gmail.com> wrote: > >> On Tue, Dec 8, 2009 at 2:08 AM, Lutger <lutger.blijdestijn@gmail.com> wrote: >>> Since a while some extern(C) functions which take arrays seem to be >>> broken. >>> Can anybody clarify /confirm how they should be declared? >>> >>> For example I stumbled upon this: >>> >>> import core.sys.posix.unistd, std.stdio; >>> >>> void main() >>> { >>> int[2] fd; >>> writeln( pipe(fd) ); // failes with errno == EFAULT >>> } >>> >>> In core.sys.posix.unistd, pipe is declared as: int pipe(int[2]); >>> >>> >>> This works though: >>> >>> extern (C) { int pipe(int*); } >>> >>> void main() >>> { >>> int[2] fd; >>> writeln( pipe(fd.ptr) ); >>> } >> >> (Assuming you're talking about D2 here...) >> A few releases ago fixed-size arrays changed to be pass-by-value. >> But I guess there's still some logic in there to interpret int[2] as >> int* when inside an extern(C) block. > > No it compiles *because* that logic is not there. It now thinks int[2] is a pass-by-value entity. It links because you are using C linkage which does not do name-mangling. I could define pipe as: > > extern (C) int pipe(char c, int x, float y); > > and it will still link :) Interesting, I didn't realize that but it makes sense! > >> It does seem like there's a bug there, though. I think pipe(fd) in the first case should fail to compile because it's attempting to pass by value where a pointer is expected. > > The error is either: > > a) you now need to declare C functions that were declared in C taking an > array to taking a pointer, so core.sys.posix.unistd (and likely others) > needs to be fixed. > b) as you suggested, inside a C block, int[2] should be interpreted as int > *. > > I'd prefer a, because I don't care much about direct translation of C headers :) If b is chosen as a solution, I'd also like to have the compiler automatically pass the pointer when calling a C function. > > -Steve Thanks for the explanation, looks like there is some work to do in the binding department. This looks like a case where a piece of C code silently does something different in D. |
Copyright © 1999-2021 by the D Language Foundation