Callbacks in D as void functions

2014-11-13 Thread Wsdes via Digitalmars-d-learn

Hi all,

I already posted this to Code Project, but maybe you have a
solution for my problem.

I am trying to write a wrapper for a C API in D. In C I have the
following definition of a callback type:

typedef void (*Callback)(void*);

In a struct all members are of the type Callback. In the main
function each member is assigned a function like this:

Events.OnData = MyDtaCB;

Here the MyDtaCB function has no prototype but is defined as
follows:

void MyDtaCB(void* pVoid){
// Do stuff
}

Now I tried to port this to D. The wiki says that callback
functions should be declared as integer functions, so my D code
looks like this:

extern (C) alias CEventCallback_t = int function(int, int);
extern (C) CEventCallback_t MyDtaCB(void*);

Here's the catch: when I try to assign the MyDtaCB function to a
member of the Events struct, I get a compilation error because
MyDtaCB is a void function and therefore returns no value. Seems
to work in C, though, but I don't know how to handle this in D.

The D tutorial has a function called getCallback() which returns
the void function but itself has the Callback type as return
value. However, in D this would lead to the same error as before
since the void function has no non-empty return value.

Any suggestions how to accomplish this? My thought now was to
screw the function definitions of the C API and implement them in
D. But what's the point in having the API then?

Thanks in advance.


Re: Callbacks in D as void functions

2014-11-13 Thread bearophile via Digitalmars-d-learn

Wsdes:


The wiki says that callback
functions should be declared as integer functions,


What's bad in returning void?

Bye,
bearophile


Re: Callbacks in D as void functions

2014-11-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 11/13/14 9:49 AM, Wsdes wrote:

Hi all,

I already posted this to Code Project, but maybe you have a
solution for my problem.

I am trying to write a wrapper for a C API in D. In C I have the
following definition of a callback type:

typedef void (*Callback)(void*);


in D, this would be:

alias Callback = void function(void *);


In a struct all members are of the type Callback. In the main
function each member is assigned a function like this:

Events.OnData = MyDtaCB;

Here the MyDtaCB function has no prototype but is defined as
follows:

void MyDtaCB(void* pVoid){
// Do stuff
}

Now I tried to port this to D. The wiki says that callback
functions should be declared as integer functions, so my D code
looks like this:

extern (C) alias CEventCallback_t = int function(int, int);
extern (C) CEventCallback_t MyDtaCB(void*);


This doesn't look right. MyDtaCB is a function taking void *, that 
returns a function pointer.


Can you point at the wiki you are talking about?


Here's the catch: when I try to assign the MyDtaCB function to a
member of the Events struct, I get a compilation error because
MyDtaCB is a void function and therefore returns no value. Seems
to work in C, though, but I don't know how to handle this in D.


C is a lot looser in function pointer types.

Without more context of what you are doing, it's hard to diagnose this 
any further.


-Steve


Re: Callbacks in D as void functions

2014-11-13 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 13 November 2014 at 14:50:00 UTC, Wsdes wrote:

I am trying to write a wrapper for a C API in D. In C I have the
following definition of a callback type:

typedef void (*Callback)(void*);


I would translate this directly to D:

extern(C) alias Callback = void function(void*);



Here the MyDtaCB function has no prototype but is defined as
follows:

void MyDtaCB(void* pVoid){
// Do stuff
}


And don't forget extern(C) on this too:

extern(C) void MyDtaCB(void* pVoid) {

}


And assign it to the struct:

Events.OnData = MyDtaCB;



Unless you have a link to the wiki that talks about ints, maybe 
that says something different, but I like to keep my C and D code 
that calls it looking pretty much the same when I can.


Re: Callbacks in D as void functions

2014-11-13 Thread Wsdes via Digitalmars-d-learn
On Thursday, 13 November 2014 at 15:17:45 UTC, Adam D. Ruppe 
wrote:

On Thursday, 13 November 2014 at 14:50:00 UTC, Wsdes wrote:
I am trying to write a wrapper for a C API in D. In C I have 
the

following definition of a callback type:

typedef void (*Callback)(void*);


I would translate this directly to D:

extern(C) alias Callback = void function(void*);



Here the MyDtaCB function has no prototype but is defined as
follows:

void MyDtaCB(void* pVoid){
// Do stuff
}


And don't forget extern(C) on this too:

extern(C) void MyDtaCB(void* pVoid) {

}


And assign it to the struct:

Events.OnData = MyDtaCB;



Unless you have a link to the wiki that talks about ints, maybe 
that says something different, but I like to keep my C and D 
code that calls it looking pretty much the same when I can.


Hi,

thank you everybody for your replies.

First of all, the link to the wiki that has an example of 
callbacks in C and D:

http://dlang.org/interfaceToC.html

Secondly, I tried your code and that was exactly what I was 
thinking and what I tried before. Then I thought I'd turn to the 
wiki example, so that's where the int function came from. In the 
meantime I changed that to return void so I gave you my old code 
:(


Anyway, I think I got the problem solved. Well, there seems to 
never have been any problem as I am taught now. I asked the 
developer of the C API this morning if I should try to implement 
the callback functions redundantly in D and he said he will have 
a look with me later. So now it turns out that I cannot call the 
extern callback function because it's not provided within the 
library O.O I was already wondering why there are no prototypes 
to these callback functions but I assumed they are provided from 
another library that I don't have direct access to...


So the solution to my problem finally is to define the function 
in my D file and then cast the function pointer to the Callback 
type like this:


void MyDtaCB(void* v){
// Do stuff
}

Events.OnData = cast(Callback) MyDtaCB;

At least this one compiles. Now I'm facing other problems with 
struct members but I guess I'll figure this out. If not, I'll ask 
again so stay tuned for some more unsolved mysteries ;)


Still, thank you all for your effort and time. Keep it up! :)


Re: Callbacks in D as void functions

2014-11-13 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 13 November 2014 at 15:58:34 UTC, Wsdes wrote:

void MyDtaCB(void* v){
// Do stuff
}

Events.OnData = cast(Callback) MyDtaCB;


this compiles but might crash, the extern(C) is important on a 
callback to be used from a C program. I'd really recommend adding 
that to the function, even if you cast when assigning to the 
struct.


Re: Callbacks in D as void functions

2014-11-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 11/13/14 10:58 AM, Wsdes wrote:


First of all, the link to the wiki that has an example of callbacks in C
and D:
http://dlang.org/interfaceToC.html

Secondly, I tried your code and that was exactly what I was thinking and
what I tried before. Then I thought I'd turn to the wiki example, so
that's where the int function came from. In the meantime I changed that
to return void so I gave you my old code :(


The int example in the above wiki page (not technically a wiki, but 
that's OK) is because the function type in C is ALSO taking ints :)


Not all callback functions are the same. Your callback type in D should 
be the same as the C definition, but with extern(C).


Can you tell us the exact prototype of the function you are trying to 
assign, whether it is a member of a struct, class, or is an inner 
function, and the exact prototype you declared the Callback type to be? 
I don't need to see any code of the function.


-Steve


Re: Callbacks in D as void functions

2014-11-13 Thread Mike Parker via Digitalmars-d-learn

On 11/14/2014 12:58 AM, Wsdes wrote:


Anyway, I think I got the problem solved. Well, there seems to never
have been any problem as I am taught now. I asked the developer of the C
API this morning if I should try to implement the callback functions
redundantly in D and he said he will have a look with me later. So now
it turns out that I cannot call the extern callback function because
it's not provided within the library O.O I was already wondering why
there are no prototypes to these callback functions but I assumed they
are provided from another library that I don't have direct access to...


Callbacks wouldn't be implemented in the library. They are intended to 
be implemented by the user of the library. That's why they're called 
callbacks. The library calls back your function. In C, this is how 
event programming is usually handled. You pass a function pointer to the 
library and when some event occurs, the library calls your function (the 
callback).





So the solution to my problem finally is to define the function in my D
file and then cast the function pointer to the Callback type like this:

void MyDtaCB(void* v){
 // Do stuff
}

Events.OnData = cast(Callback) MyDtaCB;



Define it as extern( C ) and you don't need the cast.

extern( C ) MyDtaCB( void* v ) { ... }
Events.OnData = MyDtaCB;

Callbacks intended to be passed to C should *always* be implemented as 
extern( C ).