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