Thread overview | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 14, 2004 Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
DMD 0.109, Linux
The following program fails on line 7 with the error:
found 'extern' instead of statement
> import std.stdio;
> extern(C) void foo(int i,char c) { writef("%d, %s\n", i,c); }
> extern(C) void function(int,char) global_fp = &foo;
> void main() {
> extern(C) void function(int,char) local_fp = &foo;
> global_fp(1,'a');
> local_fp(2,'b');
> }
|
December 14, 2004 Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote:
> DMD 0.109, Linux
>
> The following program fails on line 7 with the error:
> found 'extern' instead of statement
>
>> import std.stdio;
>> extern(C) void foo(int i,char c) { writef("%d, %s\n", i,c); }
>> extern(C) void function(int,char) global_fp = &foo;
>> void main() {
>> extern(C) void function(int,char) local_fp = &foo;
>> global_fp(1,'a');
>> local_fp(2,'b');
>> }
>
>
Yeah, I was going to mention that. I tried to do that too and it didn't work...
I think the problem is that it doesn't make sense to declare a function extern(C) inside another function, thus it seems D refuses to permit any type of extern(C) reference there. But this keeps the programmer from being able to declare a function variable extern(C), which appears to be a severe limitation.
So what to do? It works in a class, so should it also work in a function? I'm not sure what the answer to that is. But I did find a bit of a cheat that works around the problem. Try:
# import std.stdio;
#
# extern (C) void foo(int i, char c)
# {
# writefln("%d, %s", i,c);
# }
#
# extern (C) typedef void function(int, char) functype;
#
# void main()
# {
# functype func;
#
# func = &foo;
#
# func(2, 'c');
# }
Alias will work too. Kind of strange, but perhaps it a safer way of achieving the same goal, anyway. Gotta love typedef and alias! :-)
-John
|
December 14, 2004 Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Reimer | John Reimer wrote: > I think the problem is that it doesn't make sense to declare a function extern(C) inside another function, thus it seems D refuses to permit any type of extern(C) reference there. But this keeps the programmer from being able to declare a function variable extern(C), which appears to be a severe limitation. I could imagine a scenario where you pass a pointer to a nested function (or even an anonymous function!) to a C library. I'm pretty sure that extern(C) says things about the calling convention (not just the mangling) and so you'd need extern(C) in that case. We probably want to be able to do: > extern(C) void RegisterCallback(extern(C) int function() foo); > void main() { > RegisterCallback(extern(C) function int() { return 0; }); > } But right now that code breaks terribly. |
December 14, 2004 Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote: > John Reimer wrote: > >> I think the problem is that it doesn't make sense to declare a function extern(C) inside another function, thus it seems D refuses to permit any type of extern(C) reference there. But this keeps the programmer from being able to declare a function variable extern(C), which appears to be a severe limitation. > > > I could imagine a scenario where you pass a pointer to a nested function (or even an anonymous function!) to a C library. I'm pretty sure that extern(C) says things about the calling convention (not just the mangling) and so you'd need extern(C) in that case. We probably want to be able to do: Yes, I belive calling convention is different for extern(C), ie order the arguments are pushed/pulled off the stack. >> extern(C) void RegisterCallback(extern(C) int function() foo); >> void main() { >> RegisterCallback(extern(C) function int() { return 0; }); >> } > > > But right now that code breaks terribly. > Okay, that sounds reasonable. You also want extern(C) to be available for function literals as well. Referring to my example, doesn't the function type declaration with extern(C) fix this problem then? The use of alias or typedef cleans up the lenghthy declarations as a bonus. Later, John |
December 14, 2004 Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote:
> John Reimer wrote:
>
>> I think the problem is that it doesn't make sense to declare a function extern(C) inside another function, thus it seems D refuses to permit any type of extern(C) reference there. But this keeps the programmer from being able to declare a function variable extern(C), which appears to be a severe limitation.
>
>
> I could imagine a scenario where you pass a pointer to a nested function (or even an anonymous function!) to a C library. I'm pretty sure that extern(C) says things about the calling convention (not just the mangling) and so you'd need extern(C) in that case. We probably want to be able to do:
>
>> extern(C) void RegisterCallback(extern(C) int function() foo);
>> void main() {
>> RegisterCallback(extern(C) function int() { return 0; });
>> }
>
>
> But right now that code breaks terribly.
>
From further testing, I see now that even with typdef or aliasing, one can't do an extern(C) function literal. Interesting. While that's a limitation, I don't think it's a very significant one since it just means that you have to declare a separate local function.
Later,
John
|
December 14, 2004 Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote:
> John Reimer wrote:
>
>> I think the problem is that it doesn't make sense to declare a function extern(C) inside another function, thus it seems D refuses to permit any type of extern(C) reference there. But this keeps the programmer from being able to declare a function variable extern(C), which appears to be a severe limitation.
>
>
> I could imagine a scenario where you pass a pointer to a nested function (or even an anonymous function!) to a C library. I'm pretty sure that extern(C) says things about the calling convention (not just the mangling) and so you'd need extern(C) in that case. We probably want to be able to do:
>
>> extern(C) void RegisterCallback(extern(C) int function() foo);
>> void main() {
>> RegisterCallback(extern(C) function int() { return 0; });
>> }
>
>
> But right now that code breaks terribly.
>
You won't believe this (or maybe you will), but the above is possible with some manipulation. D seems to be full of surprises. I tried the following and it worked:
# import std.stdio;
#
# extern (C) alias int function() functype;
#
# extern (C) void RegisterCallback ( functype fo )
# {
# int i=fo();
# writefln("%d",i);
# }
#
# void main()
# {
# RegisterCallback( cast(functype) function int() { return 100;} );
# }
Output:
100
Later,
John
|
December 14, 2004 Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Reimer | John Reimer wrote:
> Russ Lewis wrote:
>
>> John Reimer wrote:
>>
>>> I think the problem is that it doesn't make sense to declare a function extern(C) inside another function, thus it seems D refuses to permit any type of extern(C) reference there. But this keeps the programmer from being able to declare a function variable extern(C), which appears to be a severe limitation.
>>
>>
>>
>> I could imagine a scenario where you pass a pointer to a nested function (or even an anonymous function!) to a C library. I'm pretty sure that extern(C) says things about the calling convention (not just the mangling) and so you'd need extern(C) in that case. We probably want to be able to do:
>>
>>> extern(C) void RegisterCallback(extern(C) int function() foo);
>>> void main() {
>>> RegisterCallback(extern(C) function int() { return 0; });
>>> }
>>
>>
>>
>> But right now that code breaks terribly.
>>
>
> You won't believe this (or maybe you will), but the above is possible with some manipulation. D seems to be full of surprises. I tried the following and it worked:
>
> # import std.stdio;
> #
> # extern (C) alias int function() functype;
> #
> # extern (C) void RegisterCallback ( functype fo )
> # {
> # int i=fo();
> # writefln("%d",i);
> # }
> #
> # void main()
> # { # RegisterCallback( cast(functype) function int() { return 100;} );
> # }
>
> Output:
>
> 100
>
> Later,
>
> John
Now that I think about this a little more, access to function literals like this is indeed useful and important. This was one problem that I had been trying to solve awhile ago in one of my projects. It had more to do with extern(C) local functions than function literals, but the idea was the same. The fact that an extern(C) function can be passed like so is a great asset!
Later,
John
|
December 14, 2004 2nd Bug: Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Reimer | I'm pretty sure that the code you wrote below exposes another bug in the compiler. That cast would certainly be broken in any architecture where the C and D calling conventions were different.
John Reimer wrote:
> Russ Lewis wrote:
>
>> John Reimer wrote:
>>
>>> I think the problem is that it doesn't make sense to declare a function extern(C) inside another function, thus it seems D refuses to permit any type of extern(C) reference there. But this keeps the programmer from being able to declare a function variable extern(C), which appears to be a severe limitation.
>>
>>
>>
>> I could imagine a scenario where you pass a pointer to a nested function (or even an anonymous function!) to a C library. I'm pretty sure that extern(C) says things about the calling convention (not just the mangling) and so you'd need extern(C) in that case. We probably want to be able to do:
>>
>>> extern(C) void RegisterCallback(extern(C) int function() foo);
>>> void main() {
>>> RegisterCallback(extern(C) function int() { return 0; });
>>> }
>>
>>
>>
>> But right now that code breaks terribly.
>>
>
> You won't believe this (or maybe you will), but the above is possible with some manipulation. D seems to be full of surprises. I tried the following and it worked:
>
> # import std.stdio;
> #
> # extern (C) alias int function() functype;
> #
> # extern (C) void RegisterCallback ( functype fo )
> # {
> # int i=fo();
> # writefln("%d",i);
> # }
> #
> # void main()
> # { # RegisterCallback( cast(functype) function int() { return 100;} );
> # }
>
> Output:
>
> 100
>
> Later,
>
> John
|
December 14, 2004 Re: 2nd Bug: Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote:
> I'm pretty sure that the code you wrote below exposes another bug in the compiler. That cast would certainly be broken in any architecture where the C and D calling conventions were different.
>
But, I believe they are different on the pc platform. Doesn't the cast just force the calling convention expected by the argument?
I realize that you are referring to the function literal's status as an extern(D) type function as declared. Is it not possible for that to be changed by casting? I don't know enough about the low level details to comment further. Perhaps Walter will clarify?
Later,
John
|
December 14, 2004 Re: 2nd Bug: Re: Can't declare extern(C) fp in function body | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote:
> I'm pretty sure that the code you wrote below exposes another bug in the compiler. That cast would certainly be broken in any architecture where the C and D calling conventions were different.
>
Okay, I'm doing a few more tests. The bug probably doesn't show because the function doesn't take any arguments. Calling convention issues probably surface once arguments are included. I'll give it a go.
Later,
John
|
Copyright © 1999-2021 by the D Language Foundation