Thread overview
Callbacks and interfacing with C
Oct 30, 2012
Nick Sabalausky
Oct 30, 2012
Nick Sabalausky
Oct 30, 2012
bearophile
Oct 30, 2012
Andrej Mitrovic
Oct 30, 2012
Jacob Carlborg
October 30, 2012
Ok, a C function pointer like this:

    struct MyStruct{
        int (*foo)(int);
    };

Translates to D as this:

    struct MyStruct{
        int function(int) foo;
    }

But what about calling conventions? There isn't any "int extern(C)
function(int)" is there? Not sure if that would even make sense.

So do you just make sure that whatever func you assign to it is an
extern(C)? Or something else?

October 30, 2012
On 30-10-2012 11:13, Nick Sabalausky wrote:
> Ok, a C function pointer like this:
>
>      struct MyStruct{
>          int (*foo)(int);
>      };
>
> Translates to D as this:
>
>      struct MyStruct{
>          int function(int) foo;
>      }
>
> But what about calling conventions? There isn't any "int extern(C)
> function(int)" is there? Not sure if that would even make sense.
>
> So do you just make sure that whatever func you assign to it is an
> extern(C)? Or something else?
>

You generally do it this way:

alias extern (C) int function(int) MyFn;

struct MyStruct {
    MyFn foo;
}

This makes sure the calling convention is correct. In general, calling convention is part of both the function signature and function pointer type - function pointers just default to extern (D).

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
October 30, 2012
On Tue, 30 Oct 2012 11:15:55 +0100
Alex Rønne Petersen <alex@lycus.org> wrote:

> On 30-10-2012 11:13, Nick Sabalausky wrote:
> > Ok, a C function pointer like this:
> >
> >      struct MyStruct{
> >          int (*foo)(int);
> >      };
> >
> > Translates to D as this:
> >
> >      struct MyStruct{
> >          int function(int) foo;
> >      }
> >
> > But what about calling conventions? There isn't any "int extern(C)
> > function(int)" is there? Not sure if that would even make sense.
> >
> > So do you just make sure that whatever func you assign to it is an
> > extern(C)? Or something else?
> >
> 
> You generally do it this way:
> 
> alias extern (C) int function(int) MyFn;
> 
> struct MyStruct {
>      MyFn foo;
> }
> 
> This makes sure the calling convention is correct. In general, calling convention is part of both the function signature and function pointer type - function pointers just default to extern (D).
> 

Hmm, that leads me to another Q:


    extern(C): // <-- Note this

    alias int function(int) MyFn;

    struct MyStruct {
        MyFn foo1;
        int function(int) foo2;
    }

    void bar(int function(int) foo3) {...}

Which, if any, of foo1/foo2/foo3 are extern(C)? (I know bar definitely
is.)

October 30, 2012
Nick Sabalausky:

> Which, if any, of foo1/foo2/foo3 are extern(C)? (I know bar definitely is.)

A general comment: if you are not sure of the answer, then the programmer that will read your code will probably have similar problems. So in such cases it's better to try to not write that code.

Bye,
bearophile
October 30, 2012
On 10/30/12, Nick Sabalausky <SeeWebsiteToContactMe@semitwist.com> wrote:
> Which, if any, of foo1/foo2/foo3 are extern(C)? (I know bar definitely
> is.)

All of them.

void main()
{
    pragma(msg, MyFn);
    pragma(msg, typeof(MyStruct.foo2));
    pragma(msg, typeof(bar));
}

extern (C) int function(int)
extern (C) int function(int)
extern (C) void(extern (C) int function(int) foo3)
extern (C) int function(int)
extern (C) int function(int)
extern (C) void(extern (C) int function(int) foo3)

It's because extern(C): leaks everywhere, whether on purpose or not.
It can be a benefit for writing shorter code, but when reading such
code it's easy to forget to check for an extern(C): declaration at the
top and just wrongly assume that it's all extern(D).
October 30, 2012
On 2012-10-30 18:44, Andrej Mitrovic wrote:

> All of them.
>
> void main()
> {
>      pragma(msg, MyFn);
>      pragma(msg, typeof(MyStruct.foo2));
>      pragma(msg, typeof(bar));
> }
>
> extern (C) int function(int)
> extern (C) int function(int)
> extern (C) void(extern (C) int function(int) foo3)
> extern (C) int function(int)
> extern (C) int function(int)
> extern (C) void(extern (C) int function(int) foo3)
>
> It's because extern(C): leaks everywhere, whether on purpose or not.
> It can be a benefit for writing shorter code, but when reading such
> code it's easy to forget to check for an extern(C): declaration at the
> top and just wrongly assume that it's all extern(D).

It doesn't leak into local declarations in a function:

extern (C):

void foo ()
{
    alias void function () Foo;

    void function (int) a;
    auto b = cast(void function ()) a;

    pragma(msg, Foo);
    pragma(msg, typeof(a));
    pragma(msg, typeof(b));
}

void function()
void function(int)
void function()

-- 
/Jacob Carlborg