Jump to page: 1 2
Thread overview
Can't declare extern(C) fp in function body
Dec 14, 2004
Russ Lewis
Dec 14, 2004
John Reimer
Dec 14, 2004
Russ Lewis
Dec 14, 2004
John Reimer
Dec 14, 2004
John Reimer
Dec 14, 2004
John Reimer
Dec 14, 2004
John Reimer
2nd Bug: Re: Can't declare extern(C) fp in function body
Dec 14, 2004
Russ Lewis
Dec 14, 2004
John Reimer
Dec 14, 2004
John Reimer
Dec 14, 2004
John Reimer
Dec 14, 2004
John Reimer
3rd bug: Re: Can't declare extern(C) fp in function body
Dec 15, 2004
Russ Lewis
Dec 15, 2004
Thomas Kuehne
December 14, 2004
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
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
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
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
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
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
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
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
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
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
« First   ‹ Prev
1 2