View mode: basic / threaded / horizontal-split · Log in · Help
October 30, 2012
Callbacks and interfacing with C
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
Re: Callbacks and interfacing with C
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
Re: Callbacks and interfacing with C
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
Re: Callbacks and interfacing with C
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
Re: Callbacks and interfacing with C
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
Re: Callbacks and interfacing with C
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
Top | Discussion index | About this forum | D home