Re: C style callbacks fix for member callbacks

2018-05-25 Thread IntegratedDimensions via Digitalmars-d-learn
Investigating further, this does not seem to be pushed on the 
stack but set in EAX.


Hence no amount of parameter placement manipulation will work. It 
actually becomes an easy situation although this will be invalid 
as it will be be whatever value is in EAX used by the caller.


One cannot set this directly though but one does not have to use 
it. Therefor, simply using a member function here is the same as 
a static and no changes have to be made. Quite an easy fix. I do 
not know how safe it is. The docs say this is pushed and that is 
probably generally true.







Re: C style callbacks fix for member callbacks

2018-05-21 Thread IntegratedDimensions via Digitalmars-d-learn

On Monday, 21 May 2018 at 02:23:27 UTC, ag0aep6g wrote:

I tried this. Your code crashes in windows dmd x86 x64.


Hm. Works for me in a virtual machine. But I'm not surprised 
that it's fragile. It might be completely wrong, and it just 
happens to look alright on my machine.


https://run.dlang.io/is/CMNnJY

Shows the static version produces the same code as the 
non-static. The code was probably compiled on linux.


I can't tell though on my machine what is going on since I cannot 
disassemble properly and what I do see is far more complex.


Re: C style callbacks fix for member callbacks

2018-05-20 Thread ag0aep6g via Digitalmars-d-learn

I tried this. Your code crashes in windows dmd x86 x64.


Hm. Works for me in a virtual machine. But I'm not surprised that it's 
fragile. It might be completely wrong, and it just happens to look 
alright on my machine.


Re: C style callbacks fix for member callbacks

2018-05-20 Thread IntegratedDimensions via Digitalmars-d-learn

On Sunday, 20 May 2018 at 23:05:47 UTC, ag0aep6g wrote:

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) }
}


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) ().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


I tried this. Your code crashes in windows dmd x86 x64.

It really shouldn't be hacky. The only difference is the "this" 
is implicit normally when in this case it is explicit and 
possibly in a different location than one expects.


Re: C style callbacks fix for member callbacks

2018-05-20 Thread ag0aep6g via Digitalmars-d-learn

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) }
}


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) ().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


Re: C style callbacks fix for member callbacks

2018-05-20 Thread IntegratedDimensions via Digitalmars-d-learn

On Sunday, 20 May 2018 at 08:40:57 UTC, MGW wrote:
On Saturday, 19 May 2018 at 23:52:58 UTC, IntegratedDimensions 
wrote:

I have a member callback that I want to use as a C callback.



http://www.agner.org/optimize/calling_conventions.pdf

https://www.youtube.com/watch?v=xhDS377mAc4


Sorry, I can't understand Russian(wish I could!). It also does 
not seem applicable for my problem. Although It is a useful idea 
here(using D in C++).


alias callback = extern(C) int function(const(void) a, void *b, 
uint c, void* context);


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) }
}





Re: C style callbacks fix for member callbacks

2018-05-20 Thread MGW via Digitalmars-d-learn
On Saturday, 19 May 2018 at 23:52:58 UTC, IntegratedDimensions 
wrote:

I have a member callback that I want to use as a C callback.



http://www.agner.org/optimize/calling_conventions.pdf

https://www.youtube.com/watch?v=xhDS377mAc4



C style callbacks fix for member callbacks

2018-05-19 Thread IntegratedDimensions via Digitalmars-d-learn

I have a member callback that I want to use as a C callback.

This is impossible due to the `hidden this` passed as the "first" 
parameter.


The callback already makes it's last value a user pointer which I 
use as a "this".


If I make my method static extern(C) then there is no crash and 
everything works. The problem is that it is now a static function 
within the class which I want to avoid.


Because there is actually a "this pointer" I can make it a member 
function and everything works as long as the calling convention 
is right.


I was initially wrapping the callback in a delegate that made it 
all work out but I want to avoid that level of indirection since 
it should not be necessary.


I have tried manually reversing the arguments, using various 
calling conventions, etc but everything crashes except when I use 
extern(C) static without modifying the order.


extern(C) static foo(a,b,c,d)

puts the parameters on the stack as d,c,b,a

foo(a,b,c,d)

is d,c,b,a,this (? The ABI does not make it clear what order is 
pushed on the stack. It uses the terminology "passes" and I 
assume that the calling convention is C'ish although extern(C) 
matters).



works

extern(C) static foo(a,b,c,d)

does not work

static foo(d,c,b,a)

So something else is going on

"The last parameter is passed in EAX rather than being pushed on 
the stack if the following conditions are met:


It fits in EAX.
It is not a 3 byte struct.
It is not a floating point type.
"

Can someone clarify the exact calling convention process for C vs 
D along with any potential solutions to the above problem(using 
static is not a solution).


Just to make sure we are on the same page:

class
{
   void extern(C) static foo(a,b,c,mythis);
}

works while

class
{
   void extern(C) foo(a,b,c);
}

fails.

class
{
   void foo(c,b,a);
}

also fails.