www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to handle nested structs when converting C headers?

reply "Gary Willoughby" <dev nomad.so> writes:
How to handle nested structs when converting C headers?

In the following snippet i'm currently converting, how would you 
convert the nested typed union and structures? Would you declare 
them separately then use their types in the Tcl_Obj struct? or is 
there a nice way in D to nest them like C?

typedef struct Tcl_Obj {
     int refCount;		/* When 0 the object will be freed. */
     char *bytes;		/* This points to the first byte of the
				 * object's string representation. The array
				 * must be followed by a null byte (i.e., at
				 * offset length) but may also contain
				 * embedded null characters. The array's
				 * storage is allocated by ckalloc. NULL means
				 * the string rep is invalid and must be
				 * regenerated from the internal rep.  Clients
				 * should use Tcl_GetStringFromObj or
				 * Tcl_GetString to get a pointer to the byte
				 * array as a readonly value. */
     int length;			/* The number of bytes at *bytes, not
				 * including the terminating null. */
     Tcl_ObjType *typePtr;	/* Denotes the object's type. Always
				 * corresponds to the type of the object's
				 * internal rep. NULL indicates the object has
				 * no internal rep (has no type). */
     union {			/* The internal representation: */
	long longValue;		/*   - an long integer value. */
	double doubleValue;	/*   - a double-precision floating value. */
	VOID *otherValuePtr;	/*   - another, type-specific value. */
	Tcl_WideInt wideValue;	/*   - a long long value. */
	struct {		/*   - internal rep as two pointers. */
	    VOID *ptr1;
	    VOID *ptr2;
	} twoPtrValue;
	struct {		/*   - internal rep as a wide int, tightly
				 *     packed fields. */
	    VOID *ptr;		/* Pointer to digits. */
	    unsigned long value;/* Alloc, used, and signum packed into a
				 * single word. */
	} ptrAndLongRep;
     } internalRep;
} Tcl_Obj;
Dec 11 2013
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 11 December 2013 at 22:45:35 UTC, Gary Willoughby 
wrote:
 How to handle nested structs when converting C headers?
Nested structs and unions like in your example are supported in D too, same syntax, same effect.
Dec 11 2013
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 11 December 2013 at 22:54:04 UTC, Adam D. Ruppe 
wrote:
 Nested structs and unions like in your example are supported in 
 D too, same syntax, same effect.
Actually, no, not quite the same syntax, I didn't notice the name at the end of the C one (in D, the anonymous nested structs and unions are supported). But almost the same then: make them a nested type with a name after the struct or union keyword then the member. So struct TwoPtrValue { /* - internal rep as two pointers. */ VOID *ptr1; VOID *ptr2; } TwoPtrValue twoPtrValue; that's how I'd do it
Dec 11 2013
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 Nested structs and unions like in your example are supported in 
 D too, same syntax, same effect.
But don't forget to add to use "static struct" instad of "struct". Bye, bearophile
Dec 11 2013
parent reply "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 11 December 2013 at 23:12:39 UTC, bearophile wrote:
 Adam D. Ruppe:

 Nested structs and unions like in your example are supported 
 in D too, same syntax, same effect.
But don't forget to add to use "static struct" instad of "struct". Bye, bearophile
Have you got an example because i always get: tcl.d(713): Error: no identifier for declarator twoPtrValue tcl.d(718): Error: no identifier for declarator ptrAndLongRep tcl.d(719): Error: no identifier for declarator internalRep
Dec 11 2013
next sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 11 December 2013 at 23:27:57 UTC, Gary Willoughby 
wrote:
 On Wednesday, 11 December 2013 at 23:12:39 UTC, bearophile 
 wrote:
 Adam D. Ruppe:

 Nested structs and unions like in your example are supported 
 in D too, same syntax, same effect.
But don't forget to add to use "static struct" instad of "struct". Bye, bearophile
Have you got an example because i always get: tcl.d(713): Error: no identifier for declarator twoPtrValue tcl.d(718): Error: no identifier for declarator ptrAndLongRep tcl.d(719): Error: no identifier for declarator internalRep
Like this perhaps: struct Tcl_Obj { int refCount; char* bytes; int length; Tcl_ObjType* typePtr; static union internalRep { c_long longValue; double doubleValue; void* otherValuePtr; Tcl_WideInt wideValue; static struct twoPtrValue { void* ptr1; void* ptr2; } static struct ptrAndLongRep { void* ptr; c_ulong value; } } }
Dec 11 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 11 December 2013 at 23:35:04 UTC, Gary Willoughby 
wrote:
     static union internalRep
try static union InternalRep { /* note the capital letter */ /* snip */ } InternalRep internalRep;; // still need a decl
Dec 11 2013
parent reply "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 11 December 2013 at 23:38:13 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 11 December 2013 at 23:35:04 UTC, Gary Willoughby 
 wrote:
    static union internalRep
try static union InternalRep { /* note the capital letter */ /* snip */ } InternalRep internalRep;; // still need a decl
Right. But why use the static keyword here?
Dec 11 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Dec 12, 2013 at 12:54:58AM +0100, Gary Willoughby wrote:
 On Wednesday, 11 December 2013 at 23:38:13 UTC, Adam D. Ruppe wrote:
On Wednesday, 11 December 2013 at 23:35:04 UTC, Gary Willoughby
wrote:
   static union internalRep
try static union InternalRep { /* note the capital letter */ /* snip */ } InternalRep internalRep;; // still need a decl
Right. But why use the static keyword here?
Because nested structs by default carry a pointer to the containing struct (or scope), which means it adds extra baggage and you can't create the nested without also having an instance of the containing struct. T -- It is of the new things that men tire --- of fashions and proposals and improvements and change. It is the old things that startle and intoxicate. It is the old things that are young. -- G.K. Chesterton
Dec 11 2013
parent reply "Regan Heath" <regan netmail.co.nz> writes:
On Thu, 12 Dec 2013 00:04:07 -0000, H. S. Teoh <hsteoh quickfur.ath.cx>  
wrote:

 On Thu, Dec 12, 2013 at 12:54:58AM +0100, Gary Willoughby wrote:
 On Wednesday, 11 December 2013 at 23:38:13 UTC, Adam D. Ruppe wrote:
On Wednesday, 11 December 2013 at 23:35:04 UTC, Gary Willoughby
wrote:
   static union internalRep
try static union InternalRep { /* note the capital letter */ /* snip */ } InternalRep internalRep;; // still need a decl
Right. But why use the static keyword here?
Because nested structs by default carry a pointer to the containing struct (or scope), which means it adds extra baggage and you can't create the nested without also having an instance of the containing struct.
I would stop nesting the struct definition. I think that is both cleaner and closer to the original intent - the only reason it is nested in C is because C allows definition and declaration that way, and D does not. Then you don't need static at all. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 12 2013
parent "bearophile" <bearophileHUGS lycos.com> writes:
Regan Heath:

 I would stop nesting the struct definition.  I think that is 
 both cleaner and closer to the original intent - the only 
 reason it is nested in C is because C allows definition and 
 declaration that way, and D does not.  Then you don't need 
 static at all.
It's mostly a matter of style, but here I prefer a little more the nested form. It's syntactically closer to the original C file, for a D programmer "static struct" has a known and clear meaning, and putting the structs inside the other keeps the global namespace clean of those inner names. Like with nested functions putting names inside other scoped helps the programmer see they are just needed there. Bye, bearophile
Dec 12 2013
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Gary Willoughby:

 Have you got an example because i always get:

 tcl.d(713): Error: no identifier for declarator twoPtrValue
 tcl.d(718): Error: no identifier for declarator ptrAndLongRep
 tcl.d(719): Error: no identifier for declarator internalRep
In D you can't define a struct/union and use it to define an instance on the fly. You have to split definition and use in two parts. Bye, bearophile
Dec 11 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 11 December 2013 at 23:36:11 UTC, bearophile wrote:
 In D you can't define a struct/union and use it to define an 
 instance on the fly.
Well, you can if it is anonymous. struct Foo { union { struct { ubyte a; ubyte b; } ubyte[2] arr; } } That works in D, and it makes foo.a == arr[0] and foo.b == arr[1];
Dec 11 2013
parent "bearophile" <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 Well, you can if it is anonymous.

 struct Foo {
     union {
         struct { ubyte a; ubyte b; }
         ubyte[2] arr;
     }
 }

 That works in D, and it makes foo.a == arr[0] and foo.b == 
 arr[1];
Right :-) I like D structs. Bye, bearophile
Dec 11 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-12-11 23:45, Gary Willoughby wrote:
 How to handle nested structs when converting C headers?

 In the following snippet i'm currently converting, how would you convert
 the nested typed union and structures? Would you declare them separately
 then use their types in the Tcl_Obj struct? or is there a nice way in D
 to nest them like C?
Convert using DStep[1] and see what happens :) [1] https://github.com/jacob-carlborg/dstep -- /Jacob Carlborg
Dec 12 2013