Thread overview
int C function
Oct 01, 2011
Ellery Newcomer
Oct 01, 2011
Andrej Mitrovic
Oct 01, 2011
Ellery Newcomer
Oct 01, 2011
Ellery Newcomer
Oct 01, 2011
Andrej Mitrovic
Oct 01, 2011
Ellery Newcomer
Oct 01, 2011
bearophile
Oct 01, 2011
bearophile
Oct 01, 2011
Andrej Mitrovic
Oct 01, 2011
Christophe
October 01, 2011
weird error. anyone know what's going on?

[ellery@localhost d]$ cat test.d
extern(C) int puts(const char *s);
class X{
    @property void tt(int function(const char *) xz){
    }
}
void main(){
    X x = new X();
    x.tt = &puts;
}
[ellery@localhost d]$ dmd test
test.d(8): Error: function test.X.tt (int function(const const(char*))
xz) is not callable using argument types (int C function(const
const(char*) s))
test.d(8): Error: cannot implicitly convert expression (& puts) of type
int C function(const const(char*) s) to int function(const const(char*))
October 01, 2011
I think this is a side-effect of the new function pointer fixes, where you now can't implicitly convert an extern(C) function to an extern(D) function by accident (and that's a good thing). But the problem is, you can't define a function with a different linkage type inline as a type parameter. You have to use an alias instead:

extern (C) int puts(const char* s);
alias extern(C) int function(const char*) FunPtr;

class X
{
    @property void tt(FunPtr xz)
    {
    }
}

void main()
{
    X x = new X();
    x.tt = &puts;
}

(sorry for reindenting, my script does that :p)
October 01, 2011
Ellery Newcomer , dans le message (digitalmars.D.learn:29885), a écrit :
> weird error. anyone know what's going on?
> 
> [ellery@localhost d]$ cat test.d
> extern(C) int puts(const char *s);
> class X{
>     @property void tt(int function(const char *) xz){
>     }
> }
> void main(){
>     X x = new X();
>     x.tt = &puts;
> }
> [ellery@localhost d]$ dmd test
> test.d(8): Error: function test.X.tt (int function(const const(char*))
> xz) is not callable using argument types (int C function(const
> const(char*) s))
> test.d(8): Error: cannot implicitly convert expression (& puts) of type
> int C function(const const(char*) s) to int function(const const(char*))

The compiler is actually quite explicit: puts is a C function, and X.tt expects a normal D function. You can solve your problem with a wrapper. Try:

int cPuts(const char* s) { return puts(s); }

and then :
x.tt = &cPuts();

By the way, it is not very d-ish to use an "int function(const char*)".
we prefer: "int delegate(const char[])". And then:
| int cPuts(const char[] s) { return puts(toStringz(s)); }
But it depends on what you exactly are trying to do.

toStringz can be found in std.string.

-- 
Christophe
October 01, 2011
On 09/30/2011 08:20 PM, Andrej Mitrovic wrote:
> I think this is a side-effect of the new function pointer fixes, where you now can't implicitly convert an extern(C) function to an extern(D) function by accident (and that's a good thing). But the problem is, you can't define a function with a different linkage type inline as a type parameter. You have to use an alias instead:
> 
> extern (C) int puts(const char* s);
> alias extern(C) int function(const char*) FunPtr;

<code golf>

template C_function(Ret,Params...){
   // Params shall not have modifiers, because C has no modifiers,
   // therefore this is good.
   alias extern(C) Ret function(Params) C_function;
}

void input_hook(C_function!(int) hook){
   ud_set_input_hook(&obj, hook);
}

</code golf>


I presume the extern(C) is transitively applied to e.g.

extern(C):
...

void ud_set_input_hook(ud*, int function(ud*));
October 01, 2011
On 09/30/2011 08:20 PM, Andrej Mitrovic wrote:
> I think this is a side-effect of the new function pointer fixes, where you now can't implicitly convert an extern(C) function to an extern(D) function by accident (and that's a good thing). But the problem is, you can't define a function with a different linkage type inline as a type parameter. You have to use an alias instead:

wait, are there explicit ways to convert extern(C) funcs <-> extern(D)
funcs?
October 01, 2011
Ellery Newcomer:

> weird error. anyone know what's going on?

It's a good error message. In DMD 2.056head gives an even better error message:

test6.d(8): Error: function test6.X.tt (int function(const const(char*)) xz) is not callable using argument types (extern (C) int function(const const(char*) s))
test6.d(8): Error: cannot implicitly convert expression (& puts) of type extern (C) int function(const const(char*) s) to int function(const const(char*))


But the error message is not good enough yet, because "const const(char*)" needs to be written "const(char*)".

----------------------

Andrej Mitrovic:

> I think this is a side-effect of the new function pointer fixes, where
> you now can't implicitly convert an extern(C) function to an extern(D)
> function by accident (and that's a good thing).

I think it didn't perform a conversion, it just used to produce wrong code.


>  But the problem is,
> you can't define a function with a different linkage type inline as a
> type parameter.

Is this in Bugzilla already?

----------------------

Ellery Newcomer:

> wait, are there explicit ways to convert extern(C) funcs <-> extern(D) funcs?

Maybe a new future job for std.conv.to? (to convert a extern(C) func ponter to extern(D) func pointer).

Bye,
bearophile
October 01, 2011
> Maybe a new future job for std.conv.to? (to convert a extern(C) func ponter to extern(D) func pointer).

This seems useless. Please ignore this.

Bye,
bearophile
October 01, 2011
On 10/1/11, Ellery Newcomer <ellery-newcomer@utulsa.edu> wrote:
> On 09/30/2011 08:20 PM, Andrej Mitrovic wrote:
>> I think this is a side-effect of the new function pointer fixes, where you now can't implicitly convert an extern(C) function to an extern(D) function by accident (and that's a good thing). But the problem is, you can't define a function with a different linkage type inline as a type parameter. You have to use an alias instead:
>
> wait, are there explicit ways to convert extern(C) funcs <-> extern(D)
> funcs?
>

You can convert anything with an explicit cast, but it doesn't make much sense to cast between calling conventions types. The compiler used to allow taking an address of an extern(C) function and assigning it to an extern(D) function pointer. But this would just result in segfaults and memory corruption due to how parameters are passed.

Nice code-golf, btw.
October 01, 2011
On 10/01/2011 08:33 AM, Andrej Mitrovic wrote:
> On 10/1/11, Ellery Newcomer <ellery-newcomer@utulsa.edu> wrote:
>> On 09/30/2011 08:20 PM, Andrej Mitrovic wrote:
>>> I think this is a side-effect of the new function pointer fixes, where you now can't implicitly convert an extern(C) function to an extern(D) function by accident (and that's a good thing). But the problem is, you can't define a function with a different linkage type inline as a type parameter. You have to use an alias instead:
>>
>> wait, are there explicit ways to convert extern(C) funcs <-> extern(D)
>> funcs?
>>
> 
> You can convert anything with an explicit cast, but it doesn't make much sense to cast between calling conventions types. The compiler used to allow taking an address of an extern(C) function and assigning it to an extern(D) function pointer. But this would just result in segfaults and memory corruption due to how parameters are passed.

What what? C and D functions have different calling conventions?

oh, is this for variadic argument?

> 
> Nice code-golf, btw.

I think it looks horrible :)
October 01, 2011
On 10/1/11, bearophile <bearophileHUGS@lycos.com> wrote:
> I think it didn't perform a conversion, it just used to produce wrong code.

Yes, poor wording on my part.

> Is this in Bugzilla already?

I can't recall. Doesn't hurt to file it if you can't find it.