www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using a struct as a wrapper for an extern(C) opaque type, no default

reply Jeremy DeHaan <dehaan.jeremiah gmail.com> writes:
Hi all. I'm interfacing to some C code which include an opaque 
type and some C functions that create and work with a pointer to 
that type. I want to wrap up everything in a struct, and the only 
thing that seems to bug me is initialization.

Since it is C code, I obviously can't read the function that 
creates the opaque type. Not only that, I can't define a default 
constructor. What are my options here?

This is for an API that is intended to be used by people other 
than myself, so I'd like to use something that doesn't look ugly 
or isn't a hack. I really don't like the idea of using a factory 
method or overriding opCall. Am I basically out of luck and need 
to resort to one of these methods?
Dec 16 2015
parent reply Jakob Ovrum <jakobovrum gmail.com> writes:
On Thursday, 17 December 2015 at 03:31:37 UTC, Jeremy DeHaan 
wrote:
 Hi all. I'm interfacing to some C code which include an opaque 
 type and some C functions that create and work with a pointer 
 to that type. I want to wrap up everything in a struct, and the 
 only thing that seems to bug me is initialization.

 Since it is C code, I obviously can't read the function that 
 creates the opaque type. Not only that, I can't define a 
 default constructor. What are my options here?

 This is for an API that is intended to be used by people other 
 than myself, so I'd like to use something that doesn't look 
 ugly or isn't a hack. I really don't like the idea of using a 
 factory method or overriding opCall. Am I basically out of luck 
 and need to resort to one of these methods?
Using a factory function alongside disable this(); is the canonical way to do this. Although, if your struct is a reference type, you can simply allow default construction and have it mean a null reference. Using static opCall here is just a factory function with special syntax, but I think it does more harm than good.
Dec 16 2015
parent reply Jeremy DeHaan <dehaan.jeremiah gmail.com> writes:
On Thursday, 17 December 2015 at 03:43:58 UTC, Jakob Ovrum wrote:
 On Thursday, 17 December 2015 at 03:31:37 UTC, Jeremy DeHaan 
 wrote:
 Hi all. I'm interfacing to some C code which include an opaque 
 type and some C functions that create and work with a pointer 
 to that type. I want to wrap up everything in a struct, and 
 the only thing that seems to bug me is initialization.

 Since it is C code, I obviously can't read the function that 
 creates the opaque type. Not only that, I can't define a 
 default constructor. What are my options here?

 This is for an API that is intended to be used by people other 
 than myself, so I'd like to use something that doesn't look 
 ugly or isn't a hack. I really don't like the idea of using a 
 factory method or overriding opCall. Am I basically out of 
 luck and need to resort to one of these methods?
Using a factory function alongside disable this(); is the canonical way to do this. Although, if your struct is a reference type, you can simply allow default construction and have it mean a null reference. Using static opCall here is just a factory function with special syntax, but I think it does more harm than good.
Thanks. I guess what bugs me is that I always try to hide the fact that the API is a wrapper around C stuff, ie, I want to make people feel as though they're using idiomatic D. Doing something like this makes it feel like less idiomatic D and more like a wrapper. I think I have a solution that I like in my own case though. Right now I'm considering something like this: http://dpaste.com/3FH3W13
Dec 16 2015
next sibling parent Jakob Ovrum <jakobovrum gmail.com> writes:
On Thursday, 17 December 2015 at 04:05:30 UTC, Jeremy DeHaan 
wrote:
 Thanks. I guess what bugs me is that I always try to hide the 
 fact that the API is a wrapper around C stuff, ie, I want to 
 make people feel as though they're using idiomatic D. Doing 
 something like this makes it feel like less idiomatic D and 
 more like a wrapper. I think I have a solution that I like in 
 my own case though. Right now I'm considering something like 
 this: http://dpaste.com/3FH3W13
I completely understand your sentiment, but I don't see how default construction factors into it. D libraries that *aren't* wrappers around C libraries have the same restriction and have to make the same interface choices. Or did you mean something else? Your code looks good, but make sure you either disable postblit or implement the postblit operator appropriately. The Rule of Three applies well to D.
Dec 16 2015
prev sibling parent reply Jakob Ovrum <jakobovrum gmail.com> writes:
On Thursday, 17 December 2015 at 04:05:30 UTC, Jeremy DeHaan 
wrote:
 http://dpaste.com/3FH3W13
Also, I would be wary of lazy initialization. We have bad experiences with it for AAs and standard containers. A typical example would be: void foo(Wrapper w) { ... w.doTheThing(); ... } void main() { Wrapper w; foo(); w.inspect(); // `w` is still a null reference here }
Dec 16 2015
parent reply Jeremy DeHaan <dehaan.jeremiah gmail.com> writes:
On Thursday, 17 December 2015 at 04:59:20 UTC, Jakob Ovrum wrote:
 On Thursday, 17 December 2015 at 04:05:30 UTC, Jeremy DeHaan 
 wrote:
 http://dpaste.com/3FH3W13
Also, I would be wary of lazy initialization. We have bad experiences with it for AAs and standard containers. A typical example would be: void foo(Wrapper w) { ... w.doTheThing(); ... } void main() { Wrapper w; foo(); w.inspect(); // `w` is still a null reference here }
Thanks for the heads up. I'll think more on this, but you made a good point here. And I guess what I was talking about before is that using a factory method feels klunky to me. If the things I am wrapping had been written in D they could use default initialization, so it feels wrong to do otherwise. I also just don't really like factory methods. They feel like a workaround that the end user has to deal with. But that's just me.
Dec 16 2015
parent Jakob Ovrum <jakobovrum gmail.com> writes:
On Thursday, 17 December 2015 at 06:04:14 UTC, Jeremy DeHaan 
wrote:
 And I guess what I was talking about before is that using a 
 factory method feels klunky to me. If the things I am wrapping 
 had been written in D they could use default initialization, so 
 it feels wrong to do otherwise. I also just don't really like 
 factory methods. They feel like a workaround that the end user 
 has to deal with. But that's just me.
If the type you're wrapping would still be accessed through a reference type, then that reference type would have exactly the same situation. But yeah, it would allow you to make it a value type.
Dec 16 2015