digitalmars.D.learn - Passing a delegate to a C function.
- =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= (50/50) Feb 06 2006 Hi.
- Charles (18/68) Feb 09 2006 It seems like a lot of hacking just to be able to use delegate's with C...
- =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= (9/37) Feb 10 2006 Don't worry, got it working after talking with Walter in d.D.
Hi. I'm writing a binding to a C library. One of its functions has the following signature: write_to_stream(surface_t* surface, write_func_t write_func, void* closure); ... and write_func is: alias status_t function(void* closure, ubyte* data, uint length) write_func_t; This seemed to map perfectly to a D delegate. So I started looking in the reference for a way to obtain the stack frame and the function pointer of a non-static delegate but couldn't find it. Then attempted to implement the trick, that was posted in the digitalmars.D newsgroup long time ago, of creating a union with the delegate and member functions for the stack and function pointer: union WriteClosure { /*extern(C)*/ status_t delegate (ubyte* data, uint length) dg; struct { // It's this the correct order? void* closure; write_func_t write_func; } } void writeToPng(OutputStream ostream) { WriteClosure wc; wc.dg = /*extern(C)*/ delegate status_t (ubyte* data, uint length) { try { ostream.writeExact(data, length); return status_t.STATUS_SUCCESS; } catch (WriteException e) { ex = e; return status_t.STATUS_WRITE_ERROR; } }; write_to_stream(m_surface_t, wc.write_func, wc.closure); } but it throws an AccessViolation when I call the "write_to_stream" function. I think it's probably missing the extern(C) but it doesn't compile with it. This is the code that calls the function. Any pointers on how to implement this? Thanks.
Feb 06 2006
It seems like a lot of hacking just to be able to use delegate's with C , does wrapping the callback not work for you , ala: // call write to stream with a C callback that just calls our delegate // our d delegate alias int function (void *closure, ubyte* data, uint length) writeFuncDelegate; writeFuncDelegate writeCallback; // = whatever //our c callback extern ( C ) write_func_callback ( void* closure, ubyte* d, uint length ) { writeCallback(closure,d,length); } // then call write to stream with your C callback, write_func_callback write_to_stream( mySurface, &write_func_callback, myClosure ); ? "Julio César Carrascal Urquijo" <jcesar phreaker.net> wrote in message news:ds93t9$16b4$1 digitaldaemon.com...Hi. I'm writing a binding to a C library. One of its functions has the following signature: write_to_stream(surface_t* surface, write_func_t write_func, void* closure); ... and write_func is: alias status_t function(void* closure, ubyte* data, uint length) write_func_t; This seemed to map perfectly to a D delegate. So I started looking in the reference for a way to obtain the stack frame and the function pointer of a non-static delegate but couldn't find it. Then attempted to implement the trick, that was posted in the digitalmars.D newsgroup long time ago, of creating a union with the delegate and member functions for the stack and function pointer: union WriteClosure { /*extern(C)*/ status_t delegate (ubyte* data, uint length) dg; struct { // It's this the correct order? void* closure; write_func_t write_func; } } void writeToPng(OutputStream ostream) { WriteClosure wc; wc.dg = /*extern(C)*/ delegate status_t (ubyte* data, uint length) { try { ostream.writeExact(data, length); return status_t.STATUS_SUCCESS; } catch (WriteException e) { ex = e; return status_t.STATUS_WRITE_ERROR; } }; write_to_stream(m_surface_t, wc.write_func, wc.closure); } but it throws an AccessViolation when I call the "write_to_stream" function. I think it's probably missing the extern(C) but it doesn't compile with it. This is the code that calls the function. Any pointers on how to implement this? Thanks.
Feb 09 2006
Charles wrote:It seems like a lot of hacking just to be able to use delegate's with C , does wrapping the callback not work for you , ala: // call write to stream with a C callback that just calls our delegate // our d delegate alias int function (void *closure, ubyte* data, uint length) writeFuncDelegate; writeFuncDelegate writeCallback; // = whatever //our c callback extern ( C ) write_func_callback ( void* closure, ubyte* d, uint length ) { writeCallback(closure,d,length); } // then call write to stream with your C callback, write_func_callback write_to_stream( mySurface, &write_func_callback, myClosure ); ?Don't worry, got it working after talking with Walter in d.D. I don't think this would compile, though:writeCallback(closure,d,length);The closure is be passed implicitly by the compiler in D code, but of course I needed the C code to pass it as the first parameter so I could modify some variables from the calling function. The problem was that D doesn't allow extern declarations for anonymous delegates but once I tried a named delegate everything worked out. Thanks.
Feb 10 2006