www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - int C function

reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
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*))
Sep 30 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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)
Sep 30 2011
next sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
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*));
Sep 30 2011
prev sibling next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
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?
Sep 30 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Oct 01 2011
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
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 :)
Oct 01 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Oct 01 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
 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
Oct 01 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Oct 01 2011
prev sibling parent travert phare.normalesup.org (Christophe) writes:
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
Sep 30 2011