www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Reference to D class instance with a C library

reply Leandro Motta Barros <lmb stackedboxes.org> writes:
Hello,

TL;DR: Can I somehow store a reference to a D class instance in a
field of a struct from a C library I am using with my D code?

The long story:

I am writing some D code that uses a C library. This C library
provides an event handling mechanism in which events are represented
by (plain C) structs that look like this:

struct event
{
   // ...lots of event stuff...
   intptr_t user_data;
}

I would like to create an event struct that contains a reference to a
D class instance in that 'user_data' field.

As I understand (and from bad experiences in the past), object
references in D are not exactly the same thing as pointers, so I
cannot simply take the address of the class instance and stash it in
that 'user_data' field.

So, is there some way to store a reference to a D class instance in
that 'user_data' field? (I can guarantee that the D object will be
alive whenever that 'event' struct is used.)

Thanks!

LMB
Jul 13 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 13 July 2013 at 18:30:24 UTC, Leandro Motta Barros 
wrote:
 So, is there some way to store a reference to a D class 
 instance in that 'user_data' field?
Should be ok to cast the reference itself to that type - don't take the address of it, since that would be the address of a local, but just cast it: MyObject foo = new MyObject(); c_struct.user_data = cast(intptr_t) foo; And when you get it back: foo = cast(MyObject) c_struct.user_data; In D, MyObject is already basically a MyObject*, so if you did &foo, the type would be more like MyObject** which is probably why you didn't have luck doing it before.
Jul 13 2013
next sibling parent reply Leandro Motta Barros <lmb stackedboxes.org> writes:
Hey, thanks! This makes sense :-)

Am I now wondering... how safe, portable and future proof would this
be? If some future version of D implements a garbage collector capable
of moving objects around the heap, I could get in trouble, right?

LMB


On Sat, Jul 13, 2013 at 3:35 PM, Adam D. Ruppe
<destructionator gmail.com> wrote:
 On Saturday, 13 July 2013 at 18:30:24 UTC, Leandro Motta Barros wrote:
 So, is there some way to store a reference to a D class instance in that
 'user_data' field?
Should be ok to cast the reference itself to that type - don't take the address of it, since that would be the address of a local, but just cast it: MyObject foo = new MyObject(); c_struct.user_data = cast(intptr_t) foo; And when you get it back: foo = cast(MyObject) c_struct.user_data; In D, MyObject is already basically a MyObject*, so if you did &foo, the type would be more like MyObject** which is probably why you didn't have luck doing it before.
Jul 13 2013
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 13 July 2013 at 18:54:18 UTC, Leandro Motta Barros 
wrote:
 If some future version of D implements a garbage collector 
 capable of moving objects around the heap, I could get in 
 trouble, right?
Maybe, but I don't think D would do that because a lot of D code uses C libraries. At the least, I'm sure it would offer a function to pin the object so the gc doesn't move it.
Jul 13 2013
parent Leandro Motta Barros <lmb stackedboxes.org> writes:
Good. Thanks again!

LMB

On Sat, Jul 13, 2013 at 4:01 PM, Adam D. Ruppe
<destructionator gmail.com> wrote:
 On Saturday, 13 July 2013 at 18:54:18 UTC, Leandro Motta Barros wrote:
 If some future version of D implements a garbage collector capable of
 moving objects around the heap, I could get in trouble, right?
Maybe, but I don't think D would do that because a lot of D code uses C libraries. At the least, I'm sure it would offer a function to pin the object so the gc doesn't move it.
Jul 13 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-07-13 20:53, Leandro Motta Barros wrote:
 Hey, thanks! This makes sense :-)

 Am I now wondering... how safe, portable and future proof would this
 be? If some future version of D implements a garbage collector capable
 of moving objects around the heap, I could get in trouble, right?
Walter has always said that there's nothing in the language (D) that stops it from having moveable GC. In this case we would hope there would be way to pin objects. -- /Jacob Carlborg
Jul 14 2013
parent reply Leandro Motta Barros <lmb stackedboxes.org> writes:
The documentation of GC.addRoot() (mentioned by Simen), contains this
interesting piece of example code:

   // Also ensure that a moving collector does not relocate
   // the object.
   GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE);

Looks like we *already* have the way to pin objects to their current
memory location. (This compiles and is running without errors so far,
though I didn't try to look if it is actually doing something under
the hood -- which currently doesn't matter much, since the current GC
doesn't move objects).

(And yes, a GC.clrAttr() call does exist, too.)

LMB


On Sun, Jul 14, 2013 at 6:29 AM, Jacob Carlborg <doob me.com> wrote:
 On 2013-07-13 20:53, Leandro Motta Barros wrote:
 Hey, thanks! This makes sense :-)

 Am I now wondering... how safe, portable and future proof would this
 be? If some future version of D implements a garbage collector capable
 of moving objects around the heap, I could get in trouble, right?
Walter has always said that there's nothing in the language (D) that stops it from having moveable GC. In this case we would hope there would be way to pin objects. -- /Jacob Carlborg
Jul 14 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-07-15 00:06, Leandro Motta Barros wrote:
 The documentation of GC.addRoot() (mentioned by Simen), contains this
 interesting piece of example code:

     // Also ensure that a moving collector does not relocate
     // the object.
     GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE);

 Looks like we *already* have the way to pin objects to their current
 memory location. (This compiles and is running without errors so far,
 though I didn't try to look if it is actually doing something under
 the hood -- which currently doesn't matter much, since the current GC
 doesn't move objects).

 (And yes, a GC.clrAttr() call does exist, too.)
That's good to know about. But as you say, we're not there yet. -- /Jacob Carlborg
Jul 14 2013
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-07-13, 20:53, Leandro Motta Barros wrote:

 Hey, thanks! This makes sense :-)

 Am I now wondering... how safe, portable and future proof would this
 be? If some future version of D implements a garbage collector capable
 of moving objects around the heap, I could get in trouble, right?
Also note that if the pointer in C land is the only reference to the class, the garbage collector will destroy the instance when it gets around to it. There's a function GC.addRoot[1] in core.memory that can make the C struct keep the reference alive. Of course, if you have other references to the class, this should be no problem. [1]: http://dlang.org/phobos/core_memory.html#.GC.addRoot -- Simen
Jul 13 2013
prev sibling parent Leandro Motta Barros <lmb stackedboxes.org> writes:
 Also note that if the pointer in C land is the only reference to the
 class, the garbage collector will destroy the instance when it gets
 around to it.
Yup, I am aware of this. I mentioned that I can guarantee that my object will outlive the C struct...
 There's a function GC.addRoot[1] in core.memory that can
 make the C struct keep the reference alive.
...but this may be useful anyway! Thanks :-) LMB PS: The community is a big plus for D. I hope to give something back in the future :-)
Jul 13 2013