pass a delegate to an API as a context pointer?
Russell Lewis
webmaster at villagersonline.com
Tue Jul 3 09:55:37 PDT 2007
Kirk McDonald wrote:
> Russell Lewis wrote:
>> teo wrote:
>>
>>> Hi *, is it possible to pass a delegate to an API function which
>>> takes a pointer to a callback function and a context pointer? The
>>> code bellow describes what I'm trying to achieve.
>>>
>>> // C-Library
>>> typedef void (*callback)(void *context);
>>> void xyz(callback handler, void *context);
>>>
>>> // D-Program
>>> alias void function(void *context) callback;
>>> extern(C) void xyz(callback handler, void *context);
>>> alias int delegate() foo;
>>
>>
>> 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:
>>
>>
>> struct CallbackBouncer
>> {
>> int delegate() whatToCall;
>> }
>> extern(C) void CallbackBouncer_callback(void *ptr)
>> {
>> CallbackBouncer *cb = cast(CallbackBouncer*)ptr;
>> ptr.whatToCall();
>> }
>>
>> void main()
>> {
>> A a = new A();
>> CallbackBouncer *cb = new CallbackBouncer[1];
>> cb.whatToCall = &a.abc;
>> xyz( CallbackBouncer_callback, cast(void*)cb);
>> }
>>
>> // A quibble: notice that the 'int' return code in
>> // A.abc is being ignored b/c C expects a return code
>> // of void.
>>
>
> There is a serious problem with this. The garbage collector will not
> scan the C library for references. As far as it is concerned, that
> struct on the heap will have no references to it (assuming your program
> is more interesting than a single main() function, and this callback is
> being assigned in some function that returns), and it might be
> collected. Furthermore, if that delegate holds the only reference to
> that 'A' instance, it might be collected, too.
>
> You'll need to somehow keep a reference to that struct locally (that is,
> within your D code).
Good catch! As another possible solution, I think that there is an
interface into the GC to make something a "root"...that is, something
which is inherently *not* garbage. So you could save the struct that
way, too.
> Also, a minor quibble: You have to use & when getting a pointer to a
> function in D.
True.
More information about the Digitalmars-d
mailing list