www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Opaque handles...

reply Manu <turkeyman gmail.com> writes:
--001a11c3235af74a8f04e6aa986c
Content-Type: text/plain; charset=UTF-8

I've seen some discussions before about people dealing with opaque
pointers, or handle types in D.
It's a common C practise, and there seems to be uncertainty about the best
way to implement this on the D side of the fence.

So I'm looking for opinions... hit me?

I have this in C:

  struct Thing;
  Thing* MakeThing();

And in D:

  struct Thing;
  extern (C) Thing* MakeThing();

The question is, does this suck?
D currently can't allocate an array of Thing*'s for some weird reason.

Are there any concerns relating to the GC that I should be aware of when
handling pointers returned to me from C code?


So a further goal, and maybe I'll add a little back-story; my 30th birthday
game jam from a few weeks back (which is still an active thread!) was
interfacing with my engine using basically an extern(C) API precisely
mirroring the C headers.
I'm planning on joining another game jam in a couple of week, using D again
(maybe I can start another thread as long and controversial as the last
one!) ;)
But this time, I want to spend some preparation time building a much more
D-styled API to interact with. Again, I'm struggling with just how I should
wrap the C calls and opaque types up.

What do people feel is conventional, and has proven to work well?

Again, wrt the opaque pointer problem. I don't really feel using an opaque
pointer on the D side is really right.
What I really want to use is something that feels more like a class
reference, and I toyed with the idea of abusing class references to hold my
handles, and methods would internally case 'this' to my handle type before
passing it back into the C code it wraps up.
This seems okay at first, but then you realise there are serious problems
with new (wants to return new memory, I can't hook the new operator?), and
there's no way to free it automatically, since D is garbage collected
rather than ref counted >_<
(Note: I'm still fairly certain that I want a ref-counting GC in D)

So... should I make it a struct with a single void* member?

struct MyThing { void* handle; }

I kinda hate this. the struct keyword totally gives the user the wrong
impression, and people have a natural instinct to avoid passing structs
around by value, which is exactly how these objects should be handled...

So if I can't present it as a class, and a struct is a pretty shit
solution... what?

My objects are opaque handles to engine-managed resources. They are
ref-counted, and there is extern(C) API to add/release references to stuff,
which I would rather have automated in the D code...

One final problem with ref-counting in D. Since it's not a 1st class
feature and requires you to store a ref-count in your object, you can't
make your objects immutable anymore because the ref-count needs to be
bumped about as the object moves around. Anyone approached this problem?

--001a11c3235af74a8f04e6aa986c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I&#39;ve seen some discussions before about people dealing=
 with opaque pointers, or handle types in D.<div>It&#39;s a common C practi=
se, and there seems to be uncertainty about the best way to implement this =
on the D side of the fence.</div>
<div><br></div><div>So I&#39;m looking for opinions... hit me?</div><div><b=
r></div><div>I have this in C:</div><div><br></div><div>=C2=A0 struct Thing=
;</div><div>=C2=A0 Thing* MakeThing();</div><div><br></div><div>And in D:</=
div><div>
<br></div><div>=C2=A0 struct Thing;</div><div>=C2=A0 extern (C) Thing* Make=
Thing();</div><div><br></div><div>The question is, does this suck?</div><di=
v>D currently can&#39;t allocate an array of Thing*&#39;s for some weird re=
ason.</div>
<div><br></div><div>Are there any concerns relating to the GC that I should=
 be aware of when handling pointers returned to me from C code?</div><div><=
br></div><div><br></div><div>So a further goal, and maybe I&#39;ll add a li=
ttle back-story; my 30th birthday game jam from a few weeks back (which is =
still an active thread!) was interfacing with my engine using basically an =
extern(C) API precisely mirroring the C headers.</div>
<div>I&#39;m planning on joining another game jam in a couple of week, usin=
g D again (maybe I can start another thread as long and controversial as th=
e last one!) ;)</div><div>But this time, I want to spend some preparation t=
ime building a much more D-styled API to interact with. Again, I&#39;m stru=
ggling with just how I should wrap the C calls and opaque types up.</div>
<div><br></div><div>What do people feel is conventional, and has proven to =
work well?</div><div><br></div><div>Again, wrt the opaque pointer problem. =
I don&#39;t really feel using an opaque pointer on the D side is really rig=
ht.</div>
<div>What I really want to use is something that feels more like a class re=
ference, and I toyed with the idea of abusing class references to hold my h=
andles, and methods would internally case &#39;this&#39; to my handle type =
before passing it back into the C code it wraps up.</div>
<div>This seems okay at first, but then you realise there are serious probl=
ems with new (wants to return new memory, I can&#39;t hook the new operator=
?), and there&#39;s no way to free it automatically, since D is garbage col=
lected rather than ref counted &gt;_&lt;</div>
<div>(Note: I&#39;m still fairly certain that I want a ref-counting GC in D=
)</div><div><br></div><div>So... should I make it a struct with a single vo=
id* member?</div><div><br></div><div>struct MyThing { void* handle; }<br>
<br></div><div>I kinda hate this. the struct keyword totally gives the user=
 the wrong impression, and people have a natural instinct to avoid passing =
structs around by value, which is exactly how these objects should be handl=
ed...</div>
<div><br></div><div>So if I can&#39;t present it as a class, and a struct i=
s a pretty shit solution... what?</div><div><br></div><div>My objects are o=
paque handles to engine-managed resources. They are ref-counted, and there =
is extern(C) API to add/release references to stuff, which I would rather h=
ave automated in the D code...</div>
<div><br></div><div>One final problem with ref-counting in D. Since it&#39;=
s not a 1st class feature and requires you to store a ref-count in your obj=
ect, you can&#39;t make your objects immutable anymore because the ref-coun=
t needs to be bumped about as the object moves around. Anyone approached th=
is problem?</div>
</div>

--001a11c3235af74a8f04e6aa986c--
Sep 18 2013
next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 One final problem with ref-counting in D. Since it's not a 1st 
 class
 feature and requires you to store a ref-count in your object, 
 you can't
 make your objects immutable anymore because the ref-count needs 
 to be
 bumped about as the object moves around. Anyone approached this 
 problem?

I use a shared_ptr (especially if I deal with C memory).
Sep 18 2013
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 18 September 2013 at 16:05:00 UTC, Manu wrote:
 This seems okay at first, but then you realise there are 
 serious problems with new (wants to return new memory, I can't 
 hook the new operator?),

There is an override for new, but it is deprecated in d2. http://dlang.org/memory.html#newdelete
 I kinda hate this. the struct keyword totally gives the user 
 the wrong impression, and people have a natural instinct to 
 avoid passing structs around by value

...just don't do that? You don't write "ref Class obj" in D, so just pretend the struct is a class and do it the same way. The only time you'd even need to know it is a struct is if you look at the source, and there you can write struct /* but pretend it is a class! */ whatever { } Here's how I might do it. Given this simple C test header: struct Test; struct Test* makeTest(int num); void addTestRef(struct Test* t); void killTest(struct Test* t); // i should have called that releaseref lol int getNumber(struct Test* t); void setNumber(struct Test* t, int n); We might use it in D like this: // this represents the struct Test in C, our opaque pointer // (the disabled stuff is to workaround a minor dmd bug) struct c_Test { disable this(); disable this(this); } // and this is our D wrapper // always pass this by value struct Test { // the internal reference private c_Test* c_ptr; // construction can only be done publicly through the static make method disable this(); private this(c_Test* ptr) { c_ptr = ptr; } public static Test make(int num) { return Test(makeTest(num)); } // the alias this lets us call the rest of the binded C functions with UFCS without manually writing wrappers c_Test* getCPointer() { return c_ptr; } // it does a property so you can't assign to the internal pointer // you CAN break the refcounting with this, but since you have to specifically ask for the uglier c_Test* to trigger // this, it is unlikely to happen by accident. alias getCPointer this; // refcount stuff ~this() { c_ptr.killTest(); } this(this) { c_ptr.addTestRef(); } } // you might notice the above is pretty generic, perhaps it could all be a single template so you don't rewrite it for too many types. // and the C function prototypes extern(C) { c_Test* makeTest(int num); void addTestRef(c_Test* t); void killTest(c_Test* t); int getNumber(c_Test* t); void setNumber(c_Test* t, int n); } // test program import core.stdc.stdio; void foo(Test t) { printf("foo on %d\n", t.getNumber()); t.setNumber(20); } void main() { auto t = Test.make(12); auto t2 = Test.make(24); printf("about to call foo\n"); foo(t); printf("done calling foo\n"); printf("main with t == %d\n", t.getNumber()); printf("main with t2 == %d\n", t2.getNumber()); } You don't have my c implementation but it isn't special and running the program produced the following output: Test made with number 12 Test made with number 24 about to call foo aref refcount now 2 on Test 12 # refcount increased properly for the function call foo on 12 dtor refcount now 1 on Test 20 # and properly decreased when ending done calling foo main with t == 20 # setting the number in foo() correctly did it by reference main with t2 == 24 dtor refcount now 0 on Test 24 # and main is dead, so we release the ref automatically Test killed with number 24 # refcount == 0, so C free()'d it dtor refcount now 0 on Test 20 Test killed with number 20 Using UFCS for the C functions might be a little bit weird, but saves tediously writing them all out again to forward inside the struct.
Sep 18 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e01633baa1e7db604e6b2834c
Content-Type: text/plain; charset=UTF-8

On 19 September 2013 02:57, Adam D. Ruppe <destructionator gmail.com> wrote:

 On Wednesday, 18 September 2013 at 16:05:00 UTC, Manu wrote:

 This seems okay at first, but then you realise there are serious problems
 with new (wants to return new memory, I can't hook the new operator?),

There is an override for new, but it is deprecated in d2. http://dlang.org/memory.html#**newdelete<http://dlang.org/memory.html#newdelete> I kinda hate this. the struct keyword totally gives the user the wrong
 impression, and people have a natural instinct to avoid passing structs
 around by value

...just don't do that? You don't write "ref Class obj" in D, so just pretend the struct is a class and do it the same way. The only time you'd even need to know it is a struct is if you look at the source, and there you can write struct /* but pretend it is a class! */ whatever { }

Except those times when you read "struct Thing" in the documentation, or hover over it in the IDE and it says "struct Thing", or when the syntax hilighting makes it go the struct colour. It's still a struct, it's obviously a struct, and that communicates some amount of intent. What you describe is a hack, and I don't want to build the foundation of a performance-oriented library upon a hack. If that's as good as it gets, then there's a deficiency in D here that we need to think about. I also don't have faith in many compilers passing struct's-with-only-a-single-member to functions by that member's type rather than as a struct. Here's how I might do it. Given this simple C test header:
 struct Test;

 struct Test* makeTest(int num);
 void addTestRef(struct Test* t);
 void killTest(struct Test* t); // i should have called that releaseref lol
 int getNumber(struct Test* t);
 void setNumber(struct Test* t, int n);



 We might use it in D like this:


 // this represents the struct Test in C, our opaque pointer
 // (the disabled stuff is to workaround a minor dmd bug)
 struct c_Test {
          disable this();
          disable this(this);
 }

 // and this is our D wrapper
 // always pass this by value
 struct Test {
        // the internal reference
         private c_Test* c_ptr;

         // construction can only be done publicly through the static make
 method
          disable this();
         private this(c_Test* ptr) {
                 c_ptr = ptr;
         }

         public static Test make(int num) {
                 return Test(makeTest(num));
         }

         // the alias this lets us call the rest of the binded C functions
 with UFCS without manually writing wrappers
         c_Test* getCPointer() { return c_ptr; } // it does a property so
 you can't assign to the internal pointer
         // you CAN break the refcounting with this, but since you have to
 specifically ask for the uglier c_Test* to trigger
         // this, it is unlikely to happen by accident.
         alias getCPointer this;

         // refcount stuff
         ~this() {
                 c_ptr.killTest();
         }
         this(this) {
                 c_ptr.addTestRef();
         }
 }

 // you might notice the above is pretty generic, perhaps it could all be a
 single template so you don't rewrite it for too many types.

 // and the C function prototypes
 extern(C) {
         c_Test* makeTest(int num);
         void addTestRef(c_Test* t);
         void killTest(c_Test* t);

         int getNumber(c_Test* t);
         void setNumber(c_Test* t, int n);
 }

 // test program
 import core.stdc.stdio;
 void foo(Test t) {
         printf("foo on %d\n", t.getNumber());
         t.setNumber(20);
 }

 void main() {
         auto t = Test.make(12);
         auto t2 = Test.make(24);

         printf("about to call foo\n");
         foo(t);
         printf("done calling foo\n");

         printf("main with t  == %d\n", t.getNumber());
         printf("main with t2 == %d\n", t2.getNumber());
 }




 You don't have my c implementation but it isn't special and running the
 program produced the following output:

 Test made with number 12
 Test made with number 24
 about to call foo
 aref refcount now 2 on Test 12 # refcount increased properly for the
 function call
 foo on 12
 dtor refcount now 1 on Test 20 # and properly decreased when ending
 done calling foo
 main with t  == 20 # setting the number in foo() correctly did it by
 reference
 main with t2 == 24
 dtor refcount now 0 on Test 24 # and main is dead, so we release the ref
 automatically
 Test killed with number 24 # refcount == 0, so C free()'d it
 dtor refcount now 0 on Test 20
 Test killed with number 20




 Using UFCS for the C functions might be a little bit weird, but saves
 tediously writing them all out again to forward inside the struct.

Well, this is precisely what I've tried before, but I don't like it. It feels like a hack. Can you make me some promises about the ABI for passing that struct by value across every compiler+architecture? I don't like that it's a struct, it's NOT a struct, it's a handle. There was some discussion about windows HANDLE types recently. I can't remember where I saw it, but I felt like that was quite relevant. It even dealt with the problem of HWND implicitly casting to a HANDLE, and I also have that problem here. --089e01633baa1e7db604e6b2834c Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 19 September 2013 02:57, Adam D. Ruppe <span dir=3D"ltr= ">&lt;<a href=3D"mailto:destructionator gmail.com" target=3D"_blank">destru= ctionator gmail.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><di= v class=3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im">On Wednesday, 18 September 2013 at 16:05= :00 UTC, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> This seems okay at first, but then you realise there are serious problems w= ith new (wants to return new memory, I can&#39;t hook the new operator?),<b= r> </blockquote> <br></div> There is an override for new, but it is deprecated in d2.<br> <a href=3D"http://dlang.org/memory.html#newdelete" target=3D"_blank">http:/= /dlang.org/memory.html#<u></u>newdelete</a><div class=3D"im"><br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> I kinda hate this. the struct keyword totally gives the user the wrong impr= ession, and people have a natural instinct to avoid passing structs around = by value<br> </blockquote> <br></div> ...just don&#39;t do that? You don&#39;t write &quot;ref Class obj&quot; in= D, so just pretend the struct is a class and do it the same way.<br> <br> The only time you&#39;d even need to know it is a struct is if you look at = the source, and there you can write<br> <br> struct /* but pretend it is a class! */ whatever {<br> }<br></blockquote><div><br></div><div>Except those times when you read &quo= t;struct Thing&quot; in the documentation, or hover over it in the IDE and = it says &quot;struct Thing&quot;, or when the syntax hilighting makes it go= the struct colour.</div> <div>It&#39;s still a struct, it&#39;s obviously a struct, and that communi= cates some amount of intent.</div><div>What you describe is a hack, and I d= on&#39;t want to build the foundation of a performance-oriented library upo= n a hack. If that&#39;s as good as it gets, then there&#39;s a deficiency i= n D here that we need to think about.</div> <div><br></div><div>I also don&#39;t have faith in many compilers passing s= truct&#39;s-with-only-a-single-member to functions by that member&#39;s typ= e rather than as a struct.</div><div><br></div><blockquote class=3D"gmail_q= uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c= olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> Here&#39;s how I might do it. Given this simple C test header:<br> <br> struct Test;<br> <br> struct Test* makeTest(int num);<br> void addTestRef(struct Test* t);<br> void killTest(struct Test* t); // i should have called that releaseref lol<= br> int getNumber(struct Test* t);<br> void setNumber(struct Test* t, int n);<br> <br> <br> <br> We might use it in D like this:<br> <br> <br> // this represents the struct Test in C, our opaque pointer<br> // (the disabled stuff is to workaround a minor dmd bug)<br> struct c_Test {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 disable this();<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 disable this(this);<br> }<br> <br> // and this is our D wrapper<br> // always pass this by value<br> struct Test {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0// the internal reference<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 private c_Test* c_ptr;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // construction can only be done publicly throu= gh the static make method<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 disable this();<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 private this(c_Test* ptr) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 c_ptr =3D ptr;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 public static Test make(int num) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return Test(makeTes= t(num));<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // the alias this lets us call the rest of the = binded C functions with UFCS without manually writing wrappers<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 c_Test* getCPointer() { return c_ptr; } // it d= oes a property so you can&#39;t assign to the internal pointer<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // you CAN break the refcounting with this, but= since you have to specifically ask for the uglier c_Test* to trigger<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // this, it is unlikely to happen by accident.<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 alias getCPointer this;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // refcount stuff<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ~this() {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 c_ptr.killTest();<b= r> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 this(this) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 c_ptr.addTestRef();= <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> }<br> <br> // you might notice the above is pretty generic, perhaps it could all be a = single template so you don&#39;t rewrite it for too many types.<br> <br> // and the C function prototypes<br> extern(C) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 c_Test* makeTest(int num);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 void addTestRef(c_Test* t);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 void killTest(c_Test* t);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 int getNumber(c_Test* t);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 void setNumber(c_Test* t, int n);<br> }<br> <br> // test program<br> import core.stdc.stdio;<br> void foo(Test t) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;foo on %d\n&quot;, t.getNumber());= <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 t.setNumber(20);<br> }<br> <br> void main() {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto t =3D Test.make(12);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto t2 =3D Test.make(24);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;about to call foo\n&quot;);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 foo(t);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;done calling foo\n&quot;);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;main with t =C2=A0=3D=3D %d\n&quot= ;, t.getNumber());<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&quot;main with t2 =3D=3D %d\n&quot;, t2= .getNumber());<br> }<br> <br> <br> <br> <br> You don&#39;t have my c implementation but it isn&#39;t special and running= the program produced the following output:<br> <br> Test made with number 12<br> Test made with number 24<br> about to call foo<br> aref refcount now 2 on Test 12 # refcount increased properly for the functi= on call<br> foo on 12<br> dtor refcount now 1 on Test 20 # and properly decreased when ending<br> done calling foo<br> main with t =C2=A0=3D=3D 20 # setting the number in foo() correctly did it = by reference<br> main with t2 =3D=3D 24<br> dtor refcount now 0 on Test 24 # and main is dead, so we release the ref au= tomatically<br> Test killed with number 24 # refcount =3D=3D 0, so C free()&#39;d it<br> dtor refcount now 0 on Test 20<br> Test killed with number 20<br> <br> <br> <br> <br> Using UFCS for the C functions might be a little bit weird, but saves tedio= usly writing them all out again to forward inside the struct.<br> </blockquote></div><br></div><div class=3D"gmail_extra"><div>Well, this is = precisely what I&#39;ve tried before, but I don&#39;t like it. It feels lik= e a hack.</div><div>Can you make me some promises about the ABI for passing= that struct by value across every compiler+architecture?</div> <div><br></div><div>I don&#39;t like that it&#39;s a struct, it&#39;s NOT a= struct, it&#39;s a handle.</div><div><br></div><div>There was some discuss= ion about windows HANDLE types recently. I can&#39;t remember where I saw i= t, but I felt like that was quite relevant.</div> <div>It even dealt with the problem of HWND implicitly casting to a HANDLE,= and I also have that problem here.</div></div></div> --089e01633baa1e7db604e6b2834c--
Sep 18 2013
prev sibling next sibling parent "Tavi Cacina" <octavian.cacina outlook.com> writes:
On Wednesday, 18 September 2013 at 16:05:00 UTC, Manu wrote:
 One final problem with ref-counting in D. Since it's not a 1st 
 class
 feature and requires you to store a ref-count in your object, 
 you can't
 make your objects immutable anymore because the ref-count needs 
 to be
 bumped about as the object moves around. Anyone approached this 
 problem?

I'de like to here some guidelines regarding this too. I tried once to manage some resources with ref-counted structs. The problem was that I could not hold them in classes anymore, so for deterministic life-management I had to use just structs, everywhere...
Sep 18 2013
prev sibling next sibling parent "Kagamin" <spam here.lot> writes:
On Wednesday, 18 September 2013 at 16:05:00 UTC, Manu wrote:
 struct MyThing { void* handle; }

 I kinda hate this. the struct keyword totally gives the user 
 the wrong
 impression, and people have a natural instinct to avoid passing 
 structs
 around by value, which is exactly how these objects should be 
 handled...

You've got some wrong people, lol. How do they work with smart pointers?
Sep 19 2013
prev sibling next sibling parent "growler" <growlercab gmail.com> writes:
On Thursday, 19 September 2013 at 09:17:09 UTC, Kagamin wrote:
 On Wednesday, 18 September 2013 at 16:05:00 UTC, Manu wrote:
 struct MyThing { void* handle; }

 I kinda hate this. the struct keyword totally gives the user 
 the wrong
 impression, and people have a natural instinct to avoid 
 passing structs
 around by value, which is exactly how these objects should be 
 handled...

You've got some wrong people, lol. How do they work with smart pointers?

I had a similar problem not long ago and ended up using RefCount from std.typecons. It worked well enough for my needs, maybe it would be an option here. I'm not sure of the performance though for a game situation, you'd have to test it.
Sep 19 2013
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Thursday, 19 September 2013 at 09:53:28 UTC, growler wrote:
 On Thursday, 19 September 2013 at 09:17:09 UTC, Kagamin wrote:
 On Wednesday, 18 September 2013 at 16:05:00 UTC, Manu wrote:
 struct MyThing { void* handle; }

 I kinda hate this. the struct keyword totally gives the user 
 the wrong
 impression, and people have a natural instinct to avoid 
 passing structs
 around by value, which is exactly how these objects should be 
 handled...

You've got some wrong people, lol. How do they work with smart pointers?

I had a similar problem not long ago and ended up using RefCount from std.typecons. It worked well enough for my needs, maybe it would be an option here. I'm not sure of the performance though for a game situation, you'd have to test it.

Yes, that should be enough. But I, for my part, do not trust the phobos solution completely. Therefore I use my own.
Sep 19 2013