Re: wrapping a C style delegate

2017-08-26 Thread Ali Çehreli via Digitalmars-d-learn

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



Re: wrapping a C style delegate

2017-08-25 Thread Nicholas Wilson via Digitalmars-d-learn

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, , , 
0);

}
}

void main() {
auto s = Struct(42);
auto ms = MyStruct();
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.




Re: wrapping a C style delegate

2017-08-25 Thread Ali Çehreli via Digitalmars-d-learn

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, , , 0);
}
}

void main() {
auto s = Struct(42);
auto ms = MyStruct();
ms.addCallback((ErrorEnum ee) {
writefln("The callback is called with %s for %s", ee, ms.s);
});
}

Ali



Re: wrapping a C style delegate

2017-08-25 Thread Nicholas Wilson via Digitalmars-d-learn

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.




Re: wrapping a C style delegate

2017-08-25 Thread Kagamin via Digitalmars-d-learn
You're not specific enough. What would be semantics of such 
wrapper?


wrapping a C style delegate

2017-08-23 Thread Nicholas Wilson via Digitalmars-d-learn

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?