www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Passing this to void *

reply Tim Hsu <tim37021 gmail.com> writes:
I am a C++ game developer and I want to give it a try.

It seems "this" in Dlang is a reference instead of pointer.

How can I pass it as void *?

void foo(void *);

class Pizza {
public:
     this() {
         Pizza newone = this;
         // works but newone is actually not this pizza.
         foo(&newone);
         // this does not work..
         foo(this);
     }
}

void main() {
     Pizza pizza = new Pizza();
     // this works...
     foo(&pizza);
}
Nov 22
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Wednesday, 22 November 2017 at 15:07:08 UTC, Tim Hsu wrote:
 I am a C++ game developer and I want to give it a try.

 It seems "this" in Dlang is a reference instead of pointer.

 How can I pass it as void *?

 void foo(void *);

 class Pizza {
 public:
     this() {
         Pizza newone = this;
         // works but newone is actually not this pizza.
         foo(&newone);
         // this does not work..
         foo(this);
     }
 }

 void main() {
     Pizza pizza = new Pizza();
     // this works...
     foo(&pizza);
 }
&this will do.
Nov 22
next sibling parent reply Tim Hsu <tim37021 gmail.com> writes:
On Wednesday, 22 November 2017 at 15:07:54 UTC, Stefan Koch wrote:
 On Wednesday, 22 November 2017 at 15:07:08 UTC, Tim Hsu wrote:
 I am a C++ game developer and I want to give it a try.

 It seems "this" in Dlang is a reference instead of pointer.

 How can I pass it as void *?

 void foo(void *);

 class Pizza {
 public:
     this() {
         Pizza newone = this;
         // works but newone is actually not this pizza.
         foo(&newone);
         // this does not work..
         foo(this);
     }
 }

 void main() {
     Pizza pizza = new Pizza();
     // this works...
     foo(&pizza);
 }
&this will do.
I've tried it in the first place. ... Error: this is not an lvalue
Nov 22
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Wednesday, 22 November 2017 at 15:11:08 UTC, Tim Hsu wrote:
 On Wednesday, 22 November 2017 at 15:07:54 UTC, Stefan Koch
 &this will do.
I've tried it in the first place. ... Error: this is not an lvalue
In that case casting to void* should be fine.
Nov 22
parent Tim Hsu <tim37021 gmail.com> writes:
On Wednesday, 22 November 2017 at 15:14:32 UTC, Stefan Koch wrote:
 On Wednesday, 22 November 2017 at 15:11:08 UTC, Tim Hsu wrote:
 On Wednesday, 22 November 2017 at 15:07:54 UTC, Stefan Koch
 &this will do.
I've tried it in the first place. ... Error: this is not an lvalue
In that case casting to void* should be fine.
But..The compiler still does not produce the executable... foo(&this); app.d(17): Error: this is not an lvalue
Nov 22
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 22 November 2017 at 15:07:54 UTC, Stefan Koch wrote:
 &this will do.
Even if it were an lvalue, that would be the address of a local. You should basically NEVER do that with D classes. Just `cast(void*) this` if you must pass it to such a function.
Nov 22
next sibling parent reply Tim Hsu <tim37021 gmail.com> writes:
On Wednesday, 22 November 2017 at 15:17:33 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 22 November 2017 at 15:07:54 UTC, Stefan Koch 
 wrote:
 &this will do.
Even if it were an lvalue, that would be the address of a local. You should basically NEVER do that with D classes. Just `cast(void*) this` if you must pass it to such a function.
I am afraid what will happen when casting this reference to void * glfwSetWindowUserPointer gives us a chance to provide a pointer to userdata. so that in callback function, we can retrieve the data and don't have to declare global variable. class App { public this() { m_window = glfwCreateWindow(); glfwSetWindowUserPointer(m_window, cast(void *)(&this)); } } How do I use this function in Dlang? sorry for my bad english.
Nov 22
next sibling parent Stefan Koch <uplink.coder googlemail.com> writes:
On Wednesday, 22 November 2017 at 15:23:58 UTC, Tim Hsu wrote:
 I am afraid what will happen when casting this reference to 
 void *
a ref is a ptr. The cast will produce a ptr which is valid as long as the ref is valid.
Nov 22
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 22 November 2017 at 15:23:58 UTC, Tim Hsu wrote:
    m_window = glfwCreateWindow();
    glfwSetWindowUserPointer(m_window, cast(void *)(&this));
That that & out of there! glfwSetWindowUserPointer(m_window, cast(void *)(this)); without the &, you are fine. Then, on the other side, you cast back. Again, do NOT dereference it, just cast it: App app = cast(App) user_ptr;
Nov 22
prev sibling parent reply Dukc <ajieskola gmail.com> writes:
On Wednesday, 22 November 2017 at 15:17:33 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 22 November 2017 at 15:07:54 UTC, Stefan Koch 
 wrote:
 &this will do.
Even if it were an lvalue, that would be the address of a local. You should basically NEVER do that with D classes. Just `cast(void*) this` if you must pass it to such a function.
It's worth noting that you will still be passing different addresses to foo(void*) because classes are reference types in D (structs are not). In the constructor you're passing the address of the class object itself, but in the main function you're passing the address of the reference.
Nov 22
next sibling parent reply Tim Hsu <tim37021 gmail.com> writes:
On Wednesday, 22 November 2017 at 15:27:27 UTC, Dukc wrote:
 On Wednesday, 22 November 2017 at 15:17:33 UTC, Adam D. Ruppe 
 wrote:
 On Wednesday, 22 November 2017 at 15:07:54 UTC, Stefan Koch 
 wrote:
 &this will do.
Even if it were an lvalue, that would be the address of a local. You should basically NEVER do that with D classes. Just `cast(void*) this` if you must pass it to such a function.
It's worth noting that you will still be passing different addresses to foo(void*) because classes are reference types in D (structs are not). In the constructor you're passing the address of the class object itself, but in the main function you're passing the address of the reference.
It seems in D, reference has its own address, am I right? unlike c++
Nov 22
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 22 November 2017 at 15:31:36 UTC, Tim Hsu wrote:
 It seems in D, reference has its own address, am I right? 
 unlike c++
The local variable does have its own address. Do not take its address - avoid &this or &object. Just cast the ref itself. In D, a class this or Object variable is already like a C++ Foo*. If you & that, you get a Foo** - not what you want in most cases.
Nov 22
parent Tim Hsu <tim37021 gmail.com> writes:
On Wednesday, 22 November 2017 at 15:36:22 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 22 November 2017 at 15:31:36 UTC, Tim Hsu wrote:
 It seems in D, reference has its own address, am I right? 
 unlike c++
The local variable does have its own address. Do not take its address - avoid &this or &object. Just cast the ref itself. In D, a class this or Object variable is already like a C++ Foo*. If you & that, you get a Foo** - not what you want in most cases.
Thanks after doing some experiment I guess I finally understand class App { property void *ptr() { return cast(void *)(this); } } void printaddr(void *ptr) { writeln(ptr); } void main() { Pizza pza = new Pizza("XD"); Pizza pza2 = pza; printaddr(pza.ptr); printaddr(pza2.ptr); printaddr(&pza); printaddr(&pza2); } Result: A32000 A32000 19FDB0 19FDB4 Conclusion: pza and pza2 is two different reference variable refer to same new-ed object.
Nov 22
prev sibling parent Dukc <ajieskola gmail.com> writes:
On Wednesday, 22 November 2017 at 15:31:36 UTC, Tim Hsu wrote:
 It seems in D, reference has its own address, am I right? 
 unlike c++
In case of classes, yes. But I think function parameter references do not (or rather, of course they have since they exist in memory but it's hidden). Not sure though.
Nov 22
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 22 November 2017 at 15:27:27 UTC, Dukc wrote:
 It's worth noting that you will still be passing different 
 addresses to foo(void*) because classes are reference types in 
 D (structs are not). In the constructor you're passing the 
 address of the class object itself, but in the main function 
 you're passing the address of the reference.
No, in both cases, if you do as I say, you will be passing the same address. You cast the reference itself. Do NOT use the & operator at any point with class objects in D (unless you legit know what you are doing). Just plain cast it: `cast(void*) this` // ok. gets address of class object itself `Object o; foo(cast(void*) o);` // also ok, does same thing `cast(void*) &this` // NOT OK! DO NOT DO THIS address of a local `cast(void*) &o` // NOT OK! DO NOT DO THIS address of a local
Nov 22
parent Dukc <ajieskola gmail.com> writes:
On Wednesday, 22 November 2017 at 15:34:53 UTC, Adam D. Ruppe 
wrote:
 No, in both cases, if you do as I say, you will be passing the 
 same address.
I was referring to his version of the main function that used &. But yes, if you do a cast instead it works just as you say.
Nov 22
prev sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 22 November 2017 at 15:07:08 UTC, Tim Hsu wrote:
 I am a C++ game developer and I want to give it a try.

 It seems "this" in Dlang is a reference instead of pointer.

 How can I pass it as void *?

 void foo(void *);

 class Pizza {
 public:
     this() {
         Pizza newone = this;
         // works but newone is actually not this pizza.
         foo(&newone);
         // this does not work..
         foo(this);
     }
 }

 void main() {
     Pizza pizza = new Pizza();
     // this works...
     foo(&pizza);
 }
Note that all the examples and advice in this thread apply to _classes_, not to structs. The 'this' in a class is a pointer, since classes are reference types (like the 'this' pointer in C++) so you can cast it to a void* directly. The 'this' in a struct is a value, since structs are value types. So if you want the address of the struct from within one of the struct's methods you need to use the & operator (then it becomes a pointer and you can cast it to a void* .
Nov 22
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 11/23/17 12:57 AM, Nicholas Wilson wrote:
 On Wednesday, 22 November 2017 at 15:07:08 UTC, Tim Hsu wrote:
 I am a C++ game developer and I want to give it a try.

 It seems "this" in Dlang is a reference instead of pointer.

 How can I pass it as void *?

 void foo(void *);

 class Pizza {
 public:
     this() {
         Pizza newone = this;
         // works but newone is actually not this pizza.
         foo(&newone);
         // this does not work..
         foo(this);
     }
 }

 void main() {
     Pizza pizza = new Pizza();
     // this works...
     foo(&pizza);
 }
Note that all the examples and advice in this thread apply to _classes_, not to structs.
A further way to look at it, a class is really not the same as what you normally think as references (either ref parameter in D or & type constructor in C++). It's really simply a pointer that cannot be used with pointer math. ref parameters: * cannot be rebound (you can't make it point at another value) * don't act any differently than auto-storage variables. Making a copy does not make a new reference, but rather copies the whole thing. class references: * CAN be rebound. * copying to another variable does not copy the data, ever (you can't make a variable that represents the class data) -Steve
Nov 24