pass a delegate to an API as a context pointer?

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Tue Jul 3 03:50:40 PDT 2007


Jascha Wetzel wrote:
> teo wrote:
>> teo Wrote:
>>
>>> Russell Lewis Wrote:
>>>> Your code below shouldn't work because void* is 4 bytes (a single 
>>>> pointer) whereas a delegate is 8 bytes (two pointers).  But you can 
>>>> do this:
>>> So, my only chance is if I wrap the delegate somehow. Thanks Russell.
>>
>> By the way, I tried to pass the address of the delegate like this:
>>
>> (for details see my first post in this thread)

 From your original post:
---
alias void function(void *context) callback;
extern(C) void xyz(callback handler, void *context);
---
That first line also needs an extern(C), or callback will be a pointer 
to a function with D calling convention instead of C calling convention.

>> void test(foo f)
>> {
>>     xyz(cast(callback)&handler, cast(void*)&f);

Those casts shouldn't be necessary.
(And make sure the C function won't store the pointers somewhere, since 
the pointer to f will be invalid after test exits since it's a local 
variable)

>> }
>>
>> Unfortunately I wasn't able to convert it back to delegate later in 
>> the callback:
>>
>> static void handler(void *context)
>> {
>>     foo f = *(cast(foo*)context);
>>     int i = f();    // call A.abc();
>> }

This one also needs extern(C) to allow the C function to call it as a 
callback.

>>
>> It simply crashes. The context value is exactly the same as &f (in 
>> test). Any ideas why? Russell? Kirk?
>>
> 
> this is most likely because the pointer doesn't exist any more when the 
> C library calls back. the &f from test() becomes invalid when test 
> returns, because f goes out of scope.

I think it's probably just the mismatching calling convention. The 
handler function expects the argument in EAX (assuming DMD) while the C 
function puts it on the stack. This causes the D code to dereference 
whatever is left in EAX, which will cause a crash unless you're very 
"lucky".



More information about the Digitalmars-d mailing list