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