pass a delegate to an API as a context pointer?
Kirk McDonald
kirklin.mcdonald at gmail.com
Mon Jul 2 16:36:19 PDT 2007
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).
Also, a minor quibble: You have to use & when getting a pointer to a
function in D.
--
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
More information about the Digitalmars-d
mailing list