C style callbacks fix for member callbacks
ag0aep6g
anonymous at example.com
Sun May 20 23:05:47 UTC 2018
On 05/20/2018 06:48 PM, IntegratedDimensions wrote:
> alias callback = extern(C) int function(const(void) a, void *b, uint c,
> void* context);
(I'm assuming that `a` is supposed to be a `const(void)*`.)
> Where context acts as this.
>
> I would like to assign a D method to this callback.
>
> class
> {
> callback c;
> /*extern(C) static*/ int foo(const(void) a, void *b, uint c, void*
> context);
>
> this() { c = cast(callback)&foo; }
> }
Unless I'm misunderstanding it, the spec seems to say that the `this`
pointer is passed as if it was an additional parameter past the last one
[1].
But that doesn't seem to be true in the implementation. At least on
Linux x86-64, `this` seems to be a hidden first parameter. So when a
method is called as a `callback`, `a` becomes `this`, `b` becomes the
first explicit parameter, `c` the second, and `context` the third. So
this works:
----
import std.stdio;
alias Callback = extern(C) int function(const(void)* a, void* b, uint c,
void* context);
class C
{
int field = 43;
extern(C) int foo(void* b, uint c, C this_)
{
const(void)* a = cast(void*) this;
writeln(a, " ", b, " ", c, " ", this_.field);
return 0;
}
}
void main()
{
void* a = new int;
void* b = new int;
uint c = 42;
auto obj = new C;
Callback cb = cast(Callback) (&obj.foo).funcptr;
cb(a, b, c, cast(void*) obj);
writeln(a, " ", b, " ", c, " ", obj.field);
/* For comparison. Should print the same. */
}
----
This is all very hacky, of course. And I don't really know what I'm
doing there. So obviously, I don't recommend doing this.
But other than hacking it like that, I don't think you can pass a method
as a `callback` directly.
[1] https://dlang.org/spec/abi.html#parameters
More information about the Digitalmars-d-learn
mailing list