Thread overview | |||||
---|---|---|---|---|---|
|
February 07, 2006 Passing a delegate to a C function. | ||||
---|---|---|---|---|
| ||||
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. |
February 09, 2006 Re: Passing a delegate to a C function. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Julio César Carrascal Urquijo | 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. |
February 11, 2006 Re: Passing a delegate to a C function. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles | 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. |
Copyright © 1999-2021 by the D Language Foundation