Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
August 24, 2017 wrapping a C style delegate | ||||
---|---|---|---|---|
| ||||
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? |
August 25, 2017 Re: wrapping a C style delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | You're not specific enough. What would be semantics of such wrapper? |
August 25, 2017 Re: wrapping a C style delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | 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. |
August 25, 2017 Re: wrapping a C style delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | On 08/25/2017 04:00 PM, Nicholas Wilson wrote:
> 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.
>
>
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);
});
}
Ali
|
August 26, 2017 Re: wrapping a C style delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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);
> });
> }
>
> Ali
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.
|
August 26, 2017 Re: wrapping a C style delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | 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 |
Copyright © 1999-2021 by the D Language Foundation