Jump to page: 1 2
Thread overview
Declaring a D pointer to a C function
Jul 12, 2011
Johannes Pfau
Jul 12, 2011
Marco Cosentino
Jul 12, 2011
Trass3r
Jul 12, 2011
Johannes Pfau
Jul 12, 2011
Marco Cosentino
Jul 12, 2011
Johannes Pfau
Jul 12, 2011
Andrej Mitrovic
Jul 12, 2011
Trass3r
Jul 12, 2011
Andrej Mitrovic
Jul 12, 2011
Andrej Mitrovic
Jul 13, 2011
Daniel Murphy
Jul 13, 2011
Andrej Mitrovic
Jul 13, 2011
Daniel Murphy
July 12, 2011
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 ;-)


-- 
Johannes Pfau

July 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.
July 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.
July 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
July 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
>> -------------------------------------------------------
but it's not practical for derelict to include aliases for all 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

July 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

July 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
July 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.
July 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
July 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.
« First   ‹ Prev
1 2