pass a delegate to an API as a context pointer?

Russell Lewis webmaster at villagersonline.com
Thu Jul 5 21:40:14 PDT 2007


teo 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.
>>
> <snip>
> 
> I got it! Thanks to all of you Russell, Kirk, Jascha and Frits!
> 
> Let me summarize: the idea is to keep the delegate in a member variable of the class and pass the address of that variable as a context data. This way the address remains valid when the callback is called from within the C-library.
> 
> Perhaps it can be done in a more elegant way, but I'm satisfied with this solution:
> 
> // C-Library
> typedef void (*callback)(void *context);
> void xyz(callback handler, void *context);
> 
> // D-Program
> alias extern(C) void function(void *context) callback;
> extern(C) void xyz(callback handler, void *context);
> alias int delegate() foo;
> 
> class A
> {
> 	int abc() { return 1; }
> }
> class B
> {
> 	foo _f = null;
> 	static extern(C) void handler(void *context)
> 	{
> 		foo f = *(cast(foo*)context);
> 		int i = f(); // call A.abc();
> 	}
> 	void test(foo f)
> 	{
> 		_f = f; // this way the address remains valid
> 		xyz(&handler, &_f);
> 	}
> }
> void main()
> {
> 	A a = new A();
> 	B b = new B();
> 	b.test(&a.abc);
> 	// ...
> 	return;
> }

I don't see any problems with this implementation as it stands, but 
remember: this only works if xyz() calls your handler back 
synchronously.  If it calls back asynchronously (that is, after main() 
exits), then the GC may have run and cleaned up the 'B b' variable you 
declared in main().  Obviously, that doesn't seem likely if with 
main()...but it is quite possible if the function is just some ordinary 
function in a larger program.

Russ



More information about the Digitalmars-d mailing list