digitalmars.D.learn - Declaring a D pointer to a C function
- Johannes Pfau <spam example.com> Jul 12 2011
- Marco Cosentino <cosentino.ma gmail.com> Jul 12 2011
- Marco Cosentino <cosentino.ma gmail.com> Jul 12 2011
- Trass3r <un known.com> Jul 12 2011
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 12 2011
- Johannes Pfau <spam example.com> Jul 12 2011
- Johannes Pfau <spam example.com> Jul 12 2011
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 12 2011
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 12 2011
- Andrej Mitrovic <andrej.mitrovich gmail.com> Jul 12 2011
- "Daniel Murphy" <yebblies nospamgmail.com> Jul 13 2011
- Trass3r <un known.com> Jul 12 2011
- Andrej Mitrovic <andrej.mitrovich gmail.com> Jul 12 2011
- Andrej Mitrovic <andrej.mitrovich gmail.com> Jul 12 2011
- Andrej Mitrovic <andrej.mitrovich gmail.com> Jul 13 2011
- "Daniel Murphy" <yebblies nospamgmail.com> Jul 13 2011
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 13 2011
=46rom a discussion related to derelict: How do you write this: ------------------------------------------------------- alias extern(C) int function(void* test) FTInitFunc; FTInitFunc FT_Init_FreeType ------------------------------------------------------- without the alias? ------------------------------------------------------- extern(C) int function(void* test) FT_Init_FreeType; ------------------------------------------------------- is not the same! both are fields containing a C function pointer, but the first field has D name mangling (_D4test16FT_Init_FreeTypePUPvZi) and the second has C name mangling: (FT_Init_FreeType, which conflicts with the C function FT_Init_FreeType) And a related question from stackoverflow: (http://stackoverflow.com/questions/6257078/casting-clutteractor-to-clutter= stage) How to write this: ------------------------------------------------------- alias extern(C) void function(void*, const char*) setTitleFunc; auto clutter_stage_set_title =3D getSym!(setTitleFunc)("clutter_stage_set_title"); ------------------------------------------------------- without the alias? http://d.puremagic.com/issues/show_bug.cgi?id=3D2168 and http://d.puremagic.com/issues/show_bug.cgi?id=3D4288 seem to be related, extern(C) seems to work almost nowhere ;-) --=20 Johannes Pfau
Jul 12 2011
On 12/07/2011 11:36, Johannes Pfau wrote:From a discussion related to derelict: How do you write this: ------------------------------------------------------- alias extern(C) int function(void* test) FTInitFunc; FTInitFunc FT_Init_FreeType ------------------------------------------------------- without the alias? ------------------------------------------------------- extern(C) int function(void* test) FT_Init_FreeType; ------------------------------------------------------- is not the same! both are fields containing a C function pointer, but the first field has D name mangling (_D4test16FT_Init_FreeTypePUPvZi) and the second has C name mangling: (FT_Init_FreeType, which conflicts with the C function FT_Init_FreeType) And a related question from stackoverflow: (http://stackoverflow.com/questions/6257078/casting-clutteractor-to-clutterstage) How to write this: ------------------------------------------------------- alias extern(C) void function(void*, const char*) setTitleFunc; auto clutter_stage_set_title = getSym!(setTitleFunc)("clutter_stage_set_title"); ------------------------------------------------------- without the alias? http://d.puremagic.com/issues/show_bug.cgi?id=2168 and http://d.puremagic.com/issues/show_bug.cgi?id=4288 seem to be related, extern(C) seems to work almost nowhere ;-)
You should declare the function pointer without the "extern(C)". Example: alias int function(void* test) FTInitFunc; extern(C) int foo(void* test){ .... } FTInitFunc foo_ptr = &foo; This worked for me.
Jul 12 2011
On 12/07/2011 13:15, Trass3r wrote:You should declare the function pointer without the "extern(C)". Example: alias int function(void* test) FTInitFunc; extern(C) int foo(void* test){ .... } FTInitFunc foo_ptr = &foo; This worked for me.
That's a bug.
Oh, well, I forgot to mention that the function pointer is a callback that gets called by a linked C library. IMHO I don't think that the alias definition should carry with her the informations about the calling convention. This is a convention for the caller and the callee.
Jul 12 2011
You should declare the function pointer without the "extern(C)". Example: alias int function(void* test) FTInitFunc; extern(C) int foo(void* test){ .... } FTInitFunc foo_ptr = &foo; This worked for me.
That's a bug.
Jul 12 2011
On Tue, 12 Jul 2011 05:36:15 -0400, Johannes Pfau <spam example.com> wrote:From a discussion related to derelict: How do you write this: ------------------------------------------------------- alias extern(C) int function(void* test) FTInitFunc; FTInitFunc FT_Init_FreeType ------------------------------------------------------- without the alias? ------------------------------------------------------- extern(C) int function(void* test) FT_Init_FreeType; ------------------------------------------------------- is not the same! both are fields containing a C function pointer, but the first field has D name mangling (_D4test16FT_Init_FreeTypePUPvZi) and the second has C name mangling: (FT_Init_FreeType, which conflicts with the C function FT_Init_FreeType) And a related question from stackoverflow: (http://stackoverflow.com/questions/6257078/casting-clutteractor-to-clutterstage) How to write this: ------------------------------------------------------- alias extern(C) void function(void*, const char*) setTitleFunc; auto clutter_stage_set_title = getSym!(setTitleFunc)("clutter_stage_set_title"); ------------------------------------------------------- without the alias?
extern(C) extern(C) maybe? :) or maybe: extern(C) int function(void * test) extern(C) FT_Init_FreeType; Just some thoughts, it probably doesn't work. -Steve
Jul 12 2011
Steven Schveighoffer wrote:On Tue, 12 Jul 2011 05:36:15 -0400, Johannes Pfau <spam example.com> wrote:From a discussion related to derelict: How do you write this: ------------------------------------------------------- alias extern(C) int function(void* test) FTInitFunc; FTInitFunc FT_Init_FreeType ------------------------------------------------------- without the alias? ------------------------------------------------------- extern(C) int function(void* test) FT_Init_FreeType; ------------------------------------------------------- is not the same! both are fields containing a C function pointer, but the first field has D name mangling (_D4test16FT_Init_FreeTypePUPvZi) and the second has C name mangling: (FT_Init_FreeType, which conflicts with the C function FT_Init_FreeType) And a related question from stackoverflow: (http://stackoverflow.com/questions/6257078/casting-clutteractor-to-clutterstage) How to write this: ------------------------------------------------------- alias extern(C) void function(void*, const char*) setTitleFunc; auto clutter_stage_set_title = getSym!(setTitleFunc)("clutter_stage_set_title"); ------------------------------------------------------- without the alias?
extern(C) extern(C) maybe? :) or maybe: extern(C) int function(void * test) extern(C) FT_Init_FreeType;
Nope, that doesn't work: --------------------------------- test.d(3): no identifier for declarator int C function(void* test) test.d(3): semicolon expected, not 'extern' test.d(3): no identifier for declarator FT_Init_FreeType --------------------------------- also, if that worked, shouldn't it be equal to this? --------------------------------- extern(C) int function(void* test) FT_Init_FreeType; --------------------------------- This works, but it's not what I want. Derelict needs a _field_, FT_Init_FreeType with D name mangling. So the usual {module}.{module}.FT_Init_FreeType in mangled form. This _field_ should contain a pointer to a extern(C) function. This code with alias does just that:------------------------------------------------------- alias extern(C) int function(void* test) FTInitFunc; FTInitFunc FT_Init_FreeType -------------------------------------------------------
functions, so the above must be accomplished without the alias. I think it should be something like this: --------------------------------- extern(C) int function(void * test) extern(D) FT_Init_FreeType; (extern(C) int function(void * test)) FT_Init_FreeType; extern(C)(int function(void * test)) FT_Init_FreeType; extern(C){int function(void * test)} FT_Init_FreeType; --------------------------------- None of these work, though.Just some thoughts, it probably doesn't work. -Steve
-- Johannes Pfau
Jul 12 2011
Trass3r wrote:You should declare the function pointer without the "extern(C)". Example: alias int function(void* test) FTInitFunc; extern(C) int foo(void* test){ .... } FTInitFunc foo_ptr = &foo; This worked for me.
That's a bug.
I agree. It looks like the above code assigns a extern(C) function pointer to a field which should only accept D function pointers. I guess if you then call foo_ptr dmd will use the D calling convention and that'll crash, at least for more complicated functions. -- Johannes Pfau
Jul 12 2011
On Tue, 12 Jul 2011 09:42:22 -0400, Johannes Pfau <spam example.com> wrote:Steven Schveighoffer wrote:On Tue, 12 Jul 2011 05:36:15 -0400, Johannes Pfau <spam example.com> wrote:From a discussion related to derelict: How do you write this: ------------------------------------------------------- alias extern(C) int function(void* test) FTInitFunc; FTInitFunc FT_Init_FreeType ------------------------------------------------------- without the alias? ------------------------------------------------------- extern(C) int function(void* test) FT_Init_FreeType; ------------------------------------------------------- is not the same! both are fields containing a C function pointer, but the first field has D name mangling (_D4test16FT_Init_FreeTypePUPvZi) and the second has C name mangling: (FT_Init_FreeType, which conflicts with the C function FT_Init_FreeType) And a related question from stackoverflow: (http://stackoverflow.com/questions/6257078/casting-clutteractor-to-clutterstage) How to write this: ------------------------------------------------------- alias extern(C) void function(void*, const char*) setTitleFunc; auto clutter_stage_set_title = getSym!(setTitleFunc)("clutter_stage_set_title"); ------------------------------------------------------- without the alias?
extern(C) extern(C) maybe? :) or maybe: extern(C) int function(void * test) extern(C) FT_Init_FreeType;
Nope, that doesn't work: --------------------------------- test.d(3): no identifier for declarator int C function(void* test) test.d(3): semicolon expected, not 'extern' test.d(3): no identifier for declarator FT_Init_FreeType --------------------------------- also, if that worked, shouldn't it be equal to this? --------------------------------- extern(C) int function(void* test) FT_Init_FreeType; --------------------------------- This works, but it's not what I want. Derelict needs a _field_, FT_Init_FreeType with D name mangling. So the usual {module}.{module}.FT_Init_FreeType in mangled form. This _field_ should contain a pointer to a extern(C) function.
Oh, I misread which one did which. I thought it was the opposite. Hm... so extern(C) affects both the function pointer type and the name mangling. Interesting. But wait, don't normal D functions have C calling convention? I thought that was one of the benefits of D's ABI? -Steve
Jul 12 2011
On Tue, 12 Jul 2011 09:53:28 -0400, Steven Schveighoffer <schveiguy yahoo.com> wrote:But wait, don't normal D functions have C calling convention? I thought that was one of the benefits of D's ABI?
Tested it out, definitely is different. So this clearly needs to be addressed. -Steve
Jul 12 2011
I just had a bug where a D function is implicitly converted to an
extern(C) function pointer.
I've had this definition:
alias extern (C) void function(void* userData) PaStreamFinishedCallback;
And this extern(C) function:
PaError Pa_SetStreamFinishedCallback(PaStream* stream,
PaStreamFinishedCallback streamFinishedCallback);
And I used this callback:
void StreamFinished(void* userData)
{
auto localData = cast(TestData*)userData;
writefln("Stream Completed: %s", localData.message);
}
// this is where the binding takes place
void main() { ...; SetStreamFinishedCallback(..., &StreamFinished); }
That code is invalid. The fix is to add extern(C) to my callback:
extern(C) void StreamFinished(void* userData)
Is this going to be fixed any time soon? Allowing callbacks with D
calling convention where a C callback is expected should be an error,
and this is like the 10th time I've ran into this bug.
Jul 12 2011
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.1569.1310506439.14074.digitalmars-d-learn puremagic.com...Is this going to be fixed any time soon? Allowing callbacks with D calling convention where a C callback is expected should be an error, and this is like the 10th time I've ran into this bug.
What, the bug that annoyed me so much I fixed it myself? Yeah, this should be gone by the next release.
Jul 13 2011
Is this going to be fixed any time soon? Allowing callbacks with D calling convention where a C callback is expected should be an error, and this is like the 10th time I've ran into this bug.
http://d.puremagic.com/issues/show_bug.cgi?id=3797
Jul 12 2011
On 7/12/11, Trass3r <un known.com> wrote:Is this going to be fixed any time soon? Allowing callbacks with D calling convention where a C callback is expected should be an error, and this is like the 10th time I've ran into this bug.
http://d.puremagic.com/issues/show_bug.cgi?id=3797
Jul 12 2011
Oh there's a pull already, this is great. https://github.com/D-Programming-Language/dmd/pull/96
Jul 12 2011
On 7/13/11, Daniel Murphy <yebblies nospamgmail.com> wrote:"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.1569.1310506439.14074.digitalmars-d-learn puremagic.com...Is this going to be fixed any time soon? Allowing callbacks with D calling convention where a C callback is expected should be an error, and this is like the 10th time I've ran into this bug.
What, the bug that annoyed me so much I fixed it myself? Yeah, this should be gone by the next release.
Thanks! I've literally lost an entire day once when I was just starting using D and C together and had a calling convention mismatch. :x
Jul 13 2011
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.1607.1310570915.14074.digitalmars-d-learn puremagic.com...Thanks! I've literally lost an entire day once when I was just starting using D and C together and had a calling convention mismatch. :x
It's worse than just calling conventions - try changing the parameter types! (or basically anything except the return type)
Jul 13 2011
On Wed, 13 Jul 2011 11:32:50 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote:"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.1607.1310570915.14074.digitalmars-d-learn puremagic.com...Thanks! I've literally lost an entire day once when I was just starting using D and C together and had a calling convention mismatch. :x
It's worse than just calling conventions - try changing the parameter types! (or basically anything except the return type)
Yeah, examining the assembly, a major difference is that D passes one parameter in a register, whereas C pushes it on the stack. This means you are going to have off-by-one corruption any time you access a parameter. -Steve
Jul 13 2011









Marco Cosentino <cosentino.ma gmail.com> 