digitalmars.D.learn - Callbacks in D as void functions
- Wsdes (31/31) Nov 13 2014 Hi all,
- bearophile (4/6) Nov 13 2014 What's bad in returning void?
- Steven Schveighoffer (10/33) Nov 13 2014 in D, this would be:
- Adam D. Ruppe (11/19) Nov 13 2014 I would translate this directly to D:
- Wsdes (32/55) Nov 13 2014 Hi,
- Adam D. Ruppe (5/9) Nov 13 2014 this compiles but might crash, the extern(C) is important on a
- Steven Schveighoffer (10/17) Nov 13 2014 The int example in the above "wiki" page (not technically a wiki, but
- Mike Parker (12/26) Nov 13 2014 Callbacks wouldn't be implemented in the library. They are intended to
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.
Nov 13 2014
Wsdes:The wiki says that callback functions should be declared as integer functions,What's bad in returning void? Bye, bearophile
Nov 13 2014
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
Nov 13 2014
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.
Nov 13 2014
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: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! :)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.
Nov 13 2014
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.
Nov 13 2014
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
Nov 13 2014
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 ).
Nov 13 2014