www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Passing a delegate to a C function.

reply =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= writes:
Sorry for cross-posting but got no answer on d.D.l:


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 writeToStream(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 07 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Julio CÚsar Carrascal Urquijo" <jcesar phreaker.net> wrote in message 
news:dsb2ih$30tt$1 digitaldaemon.com...
 Any pointers on how to implement this?

C simply doesn't support the calling convention that delegates used. Therefore, the only way to make it work is to use the inline assembler in C.
Feb 07 2006
parent reply =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= writes:
Walter Bright wrote:
 C simply doesn't support the calling convention that delegates used. 
 Therefore, the only way to make it work is to use the inline assembler in C. 
 

Never mind, got it working with a nested function. Still, I would like to know how recommendable is to use a union to obtain the delegate's function pointer and stack frame?: union WriteClosure { extern(C) status_t delegate (ubyte* data, uint length) dg; struct { void* closure; write_func_t write_func; } } Seems to work on my PC but I worry that the order of the struct's members could change on another platform / compiler. Thanks.
Feb 07 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Julio CÚsar Carrascal Urquijo" <jcesar phreaker.net> wrote in message 
news:dsbmof$hgo$1 digitaldaemon.com...
 Still, I would like to know how recommendable is to use a union to obtain 
 the delegate's function pointer and stack frame?:

 union WriteClosure
 {
 extern(C) status_t delegate (ubyte* data, uint length) dg;
 struct
 {
 void* closure;
 write_func_t write_func;
 }
 }

 Seems to work on my PC but I worry that the order of the struct's members 
 could change on another platform / compiler.

It will change when, eventually, function pointers and delegates will become the same thing. That's a 2.0 thing, though.
Feb 07 2006
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Walter Bright wrote:
<snip>
 It will change when, eventually, function pointers and delegates will become 
 the same thing. That's a 2.0 thing, though. 

The same thing? I thought they were merely going to be convertible between each other. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 09 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
news:dsf4vb$1759$1 digitaldaemon.com...
 Walter Bright wrote:
 <snip>
 It will change when, eventually, function pointers and delegates will 
 become the same thing. That's a 2.0 thing, though.

The same thing? I thought they were merely going to be convertible between each other.

It's simpler if they just merge.
Feb 09 2006
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Walter Bright wrote:
 "Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
 news:dsf4vb$1759$1 digitaldaemon.com...
 Walter Bright wrote:
 <snip>
 It will change when, eventually, function pointers and delegates will 
 become the same thing. That's a 2.0 thing, though.

between each other.

It's simpler if they just merge.

But would it be near-enough as efficient? I can see that it would bloat the runtime overhead of merely obtaining a delegate.... Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 10 2006