digitalmars.D.learn - wrapping a C style delegate
- Nicholas Wilson (14/14) Aug 23 2017 I want to wrap:
- Kagamin (2/2) Aug 25 2017 You're not specific enough. What would be semantics of such
- Nicholas Wilson (14/16) Aug 25 2017 The C function I'm trying to wrap takes a function pointer which
- =?UTF-8?Q?Ali_=c3=87ehreli?= (42/56) Aug 25 2017 I think you need a variation of intermediateCallback() below. I passed
- Nicholas Wilson (10/57) Aug 25 2017 I was thinking of something along those lines: but what about the
- =?UTF-8?Q?Ali_=c3=87ehreli?= (6/14) Aug 26 2017 Good points. I think you have to store a copy of the delegate in
I want to wrap: ErrorEnum function(Struct* s, void function(Struct*, ErrorEnum status, void *userData) callback, void *userData, uint flags); as a member of a wrapping struct struct Mystruct { Struct* s; // wrapped ErrorEnum addCallback(void delegate(Struct*, ErrorEnum status)) { //... } } How do I wrap that?
Aug 23 2017
You're not specific enough. What would be semantics of such wrapper?
Aug 25 2017
On Friday, 25 August 2017 at 13:49:20 UTC, Kagamin wrote:You're not specific enough. What would be semantics of such wrapper?The C function I'm trying to wrap takes a function pointer which is essentially a delegate, but not quite: ErrorEnum function(Struct* s, void function(Struct*, ErrorEnum status, void *userData) callback, void *userData, uint flags) SomeAPIaddCallback; I want to make it a member function of a wrapping struct so I can call it like MyStruct ms = ... ms.addCallback((ErrorEnum ee) { ... }); instead of SomeAPIaddCallback(ms.s,(Struct*, ErrorEnum status, void *userData) { ... } /*doesn't become a delegate */,null,0); I'm not sure how to do it.
Aug 25 2017
On 08/25/2017 04:00 PM, Nicholas Wilson wrote:On Friday, 25 August 2017 at 13:49:20 UTC, Kagamin wrote:I think you need a variation of intermediateCallback() below. I passed the address of the delegate as userData but you can construct any context that contains everything that you need (e.g. the address of ms). import std.stdio; // The C struct struct Struct { int i; } // Some C type enum ErrorEnum { zero } // Some C function taking a callback ErrorEnum SomeAPIaddCallback(Struct* s, void function(Struct*, ErrorEnum status, void *userData) callback, void *userData, uint flags) { writeln("SomeAPIaddCallback called for object ", s); writeln("Calling the callback..."); callback(s, ErrorEnum.zero, userData); return ErrorEnum.zero; } // The callback to pass to the C function void intermediateCallback(Struct * s, ErrorEnum status, void *userData) { writeln("intermediateCallback called"); auto cb = cast(void delegate(ErrorEnum)*)userData; (*cb)(status); } // The D wrapper always passes intermediateCallback to the C function struct MyStruct { Struct * s; void addCallback(void delegate(ErrorEnum ee) callback) { SomeAPIaddCallback(s, &intermediateCallback, &callback, 0); } } void main() { auto s = Struct(42); auto ms = MyStruct(&s); ms.addCallback((ErrorEnum ee) { writefln("The callback is called with %s for %s", ee, ms.s); }); } AliYou're not specific enough. What would be semantics of such wrapper?The C function I'm trying to wrap takes a function pointer which is essentially a delegate, but not quite: ErrorEnum function(Struct* s, void function(Struct*, ErrorEnum status, void *userData) callback, void *userData, uint flags) SomeAPIaddCallback; I want to make it a member function of a wrapping struct so I can call it like MyStruct ms = ... ms.addCallback((ErrorEnum ee) { ... }); instead of SomeAPIaddCallback(ms.s,(Struct*, ErrorEnum status, void *userData) { ... } /*doesn't become a delegate */,null,0); I'm not sure how to do it.
Aug 25 2017
On Saturday, 26 August 2017 at 00:27:47 UTC, Ali Çehreli wrote:I think you need a variation of intermediateCallback() below. I passed the address of the delegate as userData but you can construct any context that contains everything that you need (e.g. the address of ms). import std.stdio; // The C struct struct Struct { int i; } // Some C type enum ErrorEnum { zero } // Some C function taking a callback ErrorEnum SomeAPIaddCallback(Struct* s, void function(Struct*, ErrorEnum status, void *userData) callback, void *userData, uint flags) { writeln("SomeAPIaddCallback called for object ", s); writeln("Calling the callback..."); callback(s, ErrorEnum.zero, userData); return ErrorEnum.zero; } // The callback to pass to the C function void intermediateCallback(Struct * s, ErrorEnum status, void *userData) { writeln("intermediateCallback called"); auto cb = cast(void delegate(ErrorEnum)*)userData; (*cb)(status); } // The D wrapper always passes intermediateCallback to the C function struct MyStruct { Struct * s; void addCallback(void delegate(ErrorEnum ee) callback) { SomeAPIaddCallback(s, &intermediateCallback, &callback, 0); } } void main() { auto s = Struct(42); auto ms = MyStruct(&s); ms.addCallback((ErrorEnum ee) { writefln("The callback is called with %s for %s", ee, ms.s); }); } AliI was thinking of something along those lines: but what about the lifetime of the passed delegate (the address of a local variable)? How can I ensure that it won't segfault when callback goes out of scope? I could new it with the GC but a) I'd rather have the wrapper be nogc and b) i'd have to hold a reference to it or pin it because SomeAPIaddCallback will be in a driver somewhere and wouldn't get scanned by the GC.
Aug 25 2017
On 08/25/2017 05:49 PM, Nicholas Wilson wrote:I was thinking of something along those lines: but what about the lifetime of the passed delegate (the address of a local variable)? How can I ensure that it won't segfault when callback goes out of scope? I could new it with the GC but a) I'd rather have the wrapper be nogc and b) i'd have to hold a reference to it or pin it because SomeAPIaddCallback will be in a driver somewhere and wouldn't get scanned by the GC.Good points. I think you have to store a copy of the delegate in MyStruct and pass e.g. the array index of it as userData to intermediateCallback(). I think a Mallocator-based array would make the wrapper nogc. Ali
Aug 26 2017