www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to convert struct to void[]?

reply mcl <mcl_member pathlink.com> writes:
I'm stuck.  What is the best way to convert a struct to a void[]?  I'm using the
socket library in phobos and I want to send an aligned struct over the network.
Here's the best solution I've come up with so far...

#template Yuck(T)
#{
#    void[] toVoid(inout T src)
#	{
#		ubyte* data = cast(ubyte*)&src;
#		ubyte[] copy = new ubyte[src.sizeof];
#		
#		foreach(ubyte b; copy)
#			b = *(data++);
#		
#		return cast(void[])copy;
#	}
#}

To convert a struct to void[], I use the following...

#struct Foo { ... }
#
#Foo f;
#void[] fv = Yuck!(Foo).toVoid(f);

Please tell me there is a better way to do this...
Sep 09 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Fri, 10 Sep 2004 01:44:51 +0000 (UTC), mcl <mcl_member pathlink.com> 
wrote:

 I'm stuck.  What is the best way to convert a struct to a void[]?  I'm 
 using the
 socket library in phobos and I want to send an aligned struct over the 
 network.
 Here's the best solution I've come up with so far...

 #template Yuck(T)
 #{
 #    void[] toVoid(inout T src)
 #	{
 #		ubyte* data = cast(ubyte*)&src;
 #		ubyte[] copy = new ubyte[src.sizeof];
 #		
 #		foreach(ubyte b; copy)
 #			b = *(data++);
 #		
 #		return cast(void[])copy;
 #	}
 #}

 To convert a struct to void[], I use the following...

 #struct Foo { ... }
 #
 #Foo f;
 #void[] fv = Yuck!(Foo).toVoid(f);

 Please tell me there is a better way to do this...

It's a little known fact that you can slice a pointer giving you an array. Slicing a void* will give you a void[]. You can also cast any memory address to a void*, So... template toVoid(Struct) { void[] toVoid(inout Struct s) { return (cast(void*)&s)[0..s.sizeof]; } } should do it. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Sep 09 2004
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 10 Sep 2004 14:22:56 +1200, Regan Heath wrote:

 On Fri, 10 Sep 2004 01:44:51 +0000 (UTC), mcl <mcl_member pathlink.com> 
 wrote:
 
 I'm stuck.  What is the best way to convert a struct to a void[]?  I'm 
 using the
 socket library in phobos and I want to send an aligned struct over the 
 network.
 Here's the best solution I've come up with so far...

 #template Yuck(T)
 #{
 #    void[] toVoid(inout T src)
 #	{
 #		ubyte* data = cast(ubyte*)&src;
 #		ubyte[] copy = new ubyte[src.sizeof];
 #		
 #		foreach(ubyte b; copy)
 #			b = *(data++);
 #		
 #		return cast(void[])copy;
 #	}
 #}

 To convert a struct to void[], I use the following...

 #struct Foo { ... }
 #
 #Foo f;
 #void[] fv = Yuck!(Foo).toVoid(f);

 Please tell me there is a better way to do this...

It's a little known fact that you can slice a pointer giving you an array. Slicing a void* will give you a void[]. You can also cast any memory address to a void*, So... template toVoid(Struct) { void[] toVoid(inout Struct s) { return (cast(void*)&s)[0..s.sizeof]; } } should do it. Regan

It does! And you don't need a template either. Foo f; void[] fv = (cast(void*)&f)[0..f.sizeof]; writefln("%d", fv.length); writefln("%X", cast(uint)&fv[0]); writefln("%X", cast(uint)&f); -- Derek Melbourne, Australia 10/Sep/04 12:45:22 PM
Sep 09 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Fri, 10 Sep 2004 12:49:47 +1000, Derek Parnell <derek psych.ward> wrote:
 On Fri, 10 Sep 2004 14:22:56 +1200, Regan Heath wrote:

 On Fri, 10 Sep 2004 01:44:51 +0000 (UTC), mcl <mcl_member pathlink.com>
 wrote:

 I'm stuck.  What is the best way to convert a struct to a void[]?  I'm
 using the
 socket library in phobos and I want to send an aligned struct over the
 network.
 Here's the best solution I've come up with so far...

 #template Yuck(T)
 #{
 #    void[] toVoid(inout T src)
 #	{
 #		ubyte* data = cast(ubyte*)&src;
 #		ubyte[] copy = new ubyte[src.sizeof];
 #		
 #		foreach(ubyte b; copy)
 #			b = *(data++);
 #		
 #		return cast(void[])copy;
 #	}
 #}

 To convert a struct to void[], I use the following..

 #struct Foo { ... }
 #
 #Foo f;
 #void[] fv = Yuck!(Foo).toVoid(f);

 Please tell me there is a better way to do this...

It's a little known fact that you can slice a pointer giving you an array. Slicing a void* will give you a void[]. You can also cast any memory address to a void*, So... template toVoid(Struct) { void[] toVoid(inout Struct s) { return (cast(void*)&s)[0..s.sizeof]; } } should do it. Regan

It does! And you don't need a template either. Foo f; void[] fv = (cast(void*)&f)[0..f.sizeof]; writefln("%d", fv.length); writefln("%X", cast(uint)&fv[0]); writefln("%X", cast(uint)&f);

Yeah. I assumed there was a reason for using a template. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Sep 09 2004
parent reply mcl <mcl_member pathlink.com> writes:
In article <opsd3hv4o15a2sq9 digitalmars.com>, Regan Heath says...
On Fri, 10 Sep 2004 12:49:47 +1000, Derek Parnell <derek psych.ward> wrote:
 On Fri, 10 Sep 2004 14:22:56 +1200, Regan Heath wrote:

 On Fri, 10 Sep 2004 01:44:51 +0000 (UTC), mcl <mcl_member pathlink.com>
 wrote:

 I'm stuck.  What is the best way to convert a struct to a void[]?  I'm
 using the
 socket library in phobos and I want to send an aligned struct over the
 network.
 Here's the best solution I've come up with so far...

 #template Yuck(T)
 #{
 #    void[] toVoid(inout T src)
 #	{
 #		ubyte* data = cast(ubyte*)&src;
 #		ubyte[] copy = new ubyte[src.sizeof];
 #		
 #		foreach(ubyte b; copy)
 #			b = *(data++);
 #		
 #		return cast(void[])copy;
 #	}
 #}

 To convert a struct to void[], I use the following..

 #struct Foo { ... }
 #
 #Foo f;
 #void[] fv = Yuck!(Foo).toVoid(f);

 Please tell me there is a better way to do this...

It's a little known fact that you can slice a pointer giving you an array. Slicing a void* will give you a void[]. You can also cast any memory address to a void*, So... template toVoid(Struct) { void[] toVoid(inout Struct s) { return (cast(void*)&s)[0..s.sizeof]; } } should do it. Regan

It does! And you don't need a template either. Foo f; void[] fv = (cast(void*)&f)[0..f.sizeof]; writefln("%d", fv.length); writefln("%X", cast(uint)&fv[0]); writefln("%X", cast(uint)&f);

Yeah. I assumed there was a reason for using a template.

The reason for the template was to abstract the code for use with different structs since it's a bit complicated. The slice trick is far more elegant, since it's a one-liner. My only concern: Is the pointer slice in place? I could see this being a problem with stack allocated structs/classes...
Sep 10 2004
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
mcl wrote:
Foo f;
void[] fv = (cast(void*)&f)[0..f.sizeof];

writefln("%d", fv.length);
writefln("%X", cast(uint)&fv[0]);
writefln("%X", cast(uint)&f);


The reason for the template was to abstract the code for use with different structs since it's a bit complicated. The slice trick is far more elegant, since it's a one-liner. My only concern: Is the pointer slice in place? I could see this being a problem with stack allocated structs/classes...

Yes. If you want to copy it, then just append .dup: void[] fv = (&f)[0..f.sizeof].dup;
Sep 10 2004
parent reply Nick <Nick_member pathlink.com> writes:
In article <cht6ve$1vma$1 digitaldaemon.com>, Russ Lewis says...
void[] fv = (&f)[0..f.sizeof].dup;

By the way, it's (&f)[0..1], not (&f)[0..f.sizeof]. If f is a Foo then (&f) is of type (Foo*), so a slice of one element will include one entire struct. I have corrected this in the wiki as well. Nick
Sep 11 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Sat, 11 Sep 2004 12:56:07 +0000 (UTC), Nick <Nick_member pathlink.com> 
wrote:
 In article <cht6ve$1vma$1 digitaldaemon.com>, Russ Lewis says...
 void[] fv = (&f)[0..f.sizeof].dup;

By the way, it's (&f)[0..1], not (&f)[0..f.sizeof]. If f is a Foo then (&f) is of type (Foo*), so a slice of one element will include one entire struct. I have corrected this in the wiki as well.

Ahhh, yes, but in this case... (cast(void*)&f)[0..f.sizeof] it is f.sizeof, isn't it? because void has a size of 1. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Sep 12 2004
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Regan Heath wrote:

 On Sat, 11 Sep 2004 12:56:07 +0000 (UTC), Nick 
 <Nick_member pathlink.com> wrote:
 
 In article <cht6ve$1vma$1 digitaldaemon.com>, Russ Lewis says...

 void[] fv = (&f)[0..f.sizeof].dup;

By the way, it's (&f)[0..1], not (&f)[0..f.sizeof]. If f is a Foo then (&f) is of type (Foo*), so a slice of one element will include one entire struct. I have corrected this in the wiki as well.

Ahhh, yes, but in this case... (cast(void*)&f)[0..f.sizeof] it is f.sizeof, isn't it? because void has a size of 1.

But Nick isn't casting to void so it's a pointer to Foo. Sean
Sep 12 2004
parent Regan Heath <regan netwin.co.nz> writes:
On Sun, 12 Sep 2004 22:08:05 -0700, Sean Kelly <sean f4.ca> wrote:
 Regan Heath wrote:

 On Sat, 11 Sep 2004 12:56:07 +0000 (UTC), Nick 
 <Nick_member pathlink.com> wrote:

 In article <cht6ve$1vma$1 digitaldaemon.com>, Russ Lewis says...

 void[] fv = (&f)[0..f.sizeof].dup;

By the way, it's (&f)[0..1], not (&f)[0..f.sizeof]. If f is a Foo then (&f) is of type (Foo*), so a slice of one element will include one entire struct. I have corrected this in the wiki as well.

Ahhh, yes, but in this case... (cast(void*)&f)[0..f.sizeof] it is f.sizeof, isn't it? because void has a size of 1.

But Nick isn't casting to void so it's a pointer to Foo.

I know. I was simply pointing out the original suggestion wasn't buggy, it turned buggy when someone changed a part of it. :) Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Sep 13 2004
prev sibling parent Nick <Nick_member pathlink.com> writes:
In article <opsd8ixnk45a2sq9 digitalmars.com>, Regan Heath says...
 Nick:
 By the way, it's (&f)[0..1], not (&f)[0..f.sizeof]. If f is a Foo then 
 (&f) is of type (Foo*), so a slice of one element will include one 
 entire struct. I have corrected this in the wiki as well.

Ahhh, yes, but in this case... (cast(void*)&f)[0..f.sizeof] it is f.sizeof, isn't it? because void has a size of 1.

That is correct. Nick
Sep 13 2004
prev sibling parent reply Sha Chancellor <schancel pacific.net> writes:
In article <opsd298iol5a2sq9 digitalmars.com>,
 Regan Heath <regan netwin.co.nz> wrote:

 It's a little known fact that you can slice a pointer giving you an array. 
 Slicing a void* will give you a void[]. You can also cast any memory 
 address to a void*, So...
 
 template toVoid(Struct)
 {
    void[] toVoid(inout Struct s)
    {
      return (cast(void*)&s)[0..s.sizeof];
    }
 }
 
 should do it.
 
 Regan

That reeks of nasty hack. Why slice a pointer to cast a struct into a void[] ??? Why can't it just be cast directly?
Sep 12 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Sun, 12 Sep 2004 07:23:08 -0700, Sha Chancellor <schancel pacific.net> 
wrote:
 In article <opsd298iol5a2sq9 digitalmars.com>,
  Regan Heath <regan netwin.co.nz> wrote:

 It's a little known fact that you can slice a pointer giving you an 
 array.
 Slicing a void* will give you a void[]. You can also cast any memory
 address to a void*, So...

 template toVoid(Struct)
 {
    void[] toVoid(inout Struct s)
    {
      return (cast(void*)&s)[0..s.sizeof];
    }
 }

 should do it.

 Regan

That reeks of nasty hack.

Not to me, but then I work in C most of the time.
 Why slice a pointer to cast a struct into a
 void[] ???  Why can't it just be cast directly?

Good question, it probably could with some compiler magic, after all a void[] is simply a pointer and a length, the compiler knows the length of the object.. Arrays already implicitly cast to void[] eg. void foo(void[] p) { } void main() { char[] string = "regan"; foo(string); } Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Sep 12 2004
parent reply Sha Chancellor <schancel pacific.net> writes:
In article <opsd8ly80b5a2sq9 digitalmars.com>,
 Regan Heath <regan netwin.co.nz> wrote:

 On Sun, 12 Sep 2004 07:23:08 -0700, Sha Chancellor <schancel pacific.net> 
 wrote:
 In article <opsd298iol5a2sq9 digitalmars.com>,
  Regan Heath <regan netwin.co.nz> wrote:

 It's a little known fact that you can slice a pointer giving you an 
 array.
 Slicing a void* will give you a void[]. You can also cast any memory
 address to a void*, So...

 template toVoid(Struct)
 {
    void[] toVoid(inout Struct s)
    {
      return (cast(void*)&s)[0..s.sizeof];
    }
 }

 should do it.

 Regan

That reeks of nasty hack.

Not to me, but then I work in C most of the time.
 Why slice a pointer to cast a struct into a
 void[] ???  Why can't it just be cast directly?

Good question, it probably could with some compiler magic, after all a void[] is simply a pointer and a length, the compiler knows the length of the object.. Arrays already implicitly cast to void[] eg. void foo(void[] p) { } void main() { char[] string = "regan"; foo(string); } Regan

I guess this bothers me:
    void[] toVoid(inout Struct s)
    {
      return (cast(void*)&s)[0..s.sizeof];
    }



You cast a pointer of S to a void* and then do an array slice. If you can slice it like an array, why do you need to slice it at all? Why can't it be implicit cast to void[] from a void* in the first place? Why is slicing necessary? IE: return (cast(void[])&s); or return (cast(void*)&s); Will either of those work? I don't have a D compiler handy.
Sep 25 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Sha Chancellor" <schancel pacific.net> wrote in message
news:schancel-0064DE.14485525092004 digitalmars.com...
 In article <opsd8ly80b5a2sq9 digitalmars.com>,
  Regan Heath <regan netwin.co.nz> wrote:

 On Sun, 12 Sep 2004 07:23:08 -0700, Sha Chancellor


 wrote:
 In article <opsd298iol5a2sq9 digitalmars.com>,
  Regan Heath <regan netwin.co.nz> wrote:

 It's a little known fact that you can slice a pointer giving you an
 array.
 Slicing a void* will give you a void[]. You can also cast any memory
 address to a void*, So...

 template toVoid(Struct)
 {
    void[] toVoid(inout Struct s)
    {
      return (cast(void*)&s)[0..s.sizeof];
    }
 }

 should do it.

 Regan

That reeks of nasty hack.

Not to me, but then I work in C most of the time.
 Why slice a pointer to cast a struct into a
 void[] ???  Why can't it just be cast directly?

Good question, it probably could with some compiler magic, after all a void[] is simply a pointer and a length, the compiler knows the length


 the object..

 Arrays already implicitly cast to void[] eg.

 void foo(void[] p)
 {
 }

 void main()
 {
    char[] string = "regan";
    foo(string);
 }

 Regan

I guess this bothers me:
    void[] toVoid(inout Struct s)
    {
      return (cast(void*)&s)[0..s.sizeof];
    }



You cast a pointer of S to a void* and then do an array slice. If you can slice it like an array, why do you need to slice it at all? Why can't it be implicit cast to void[] from a void* in the first place? Why is slicing necessary?

Because void[] has a length property and a void* doesn't, if we could implicitly cast void* to void[] what length would that array have? That is what slicing is there for, to give array length, it is also a documented way of making bounds checked array out of a pointer.
 IE:

 return (cast(void[])&s);
 or return (cast(void*)&s);

 Will either of those work?

No, first is Struct* to void[] the second is void* to return type void[]
 I don't have a D compiler handy.

Sep 26 2004
parent Sha Chancellor <schancel pacific.net> writes:
In article <cj5qg7$2uod$1 digitaldaemon.com>,
 "Ivan Senji" <ivan.senji public.srce.hr> wrote:

 Because void[] has a length property and a void* doesn't,
 if we could implicitly cast void* to void[] what length would that
 array have? That is what slicing is there for, to give array length,
 it is also a documented way of making bounds checked array out of
 a pointer.
 
 IE:

 return (cast(void[])&s);
 or return (cast(void*)&s);

 Will either of those work?

No, first is Struct* to void[] the second is void* to return type void[]

Hmmm.. That make sense now. But, I still don't like how it looks.
Sep 26 2004
prev sibling next sibling parent reply "Vathix" <vathixSpamFix dprogramming.com> writes:
"mcl" <mcl_member pathlink.com> wrote in message
news:chr0uj$rvk$1 digitaldaemon.com...
 I'm stuck.  What is the best way to convert a struct to a void[]?  I'm

 socket library in phobos and I want to send an aligned struct over the

 Here's the best solution I've come up with so far...

(&f)[0 .. 1] works just fine. Any array implicitly converts to void[].
Sep 09 2004
next sibling parent Regan Heath <regan netwin.co.nz> writes:
On Fri, 10 Sep 2004 01:15:15 -0400, Vathix 
<vathixSpamFix dprogramming.com> wrote:
 "mcl" <mcl_member pathlink.com> wrote in message
 news:chr0uj$rvk$1 digitaldaemon.com...
 I'm stuck.  What is the best way to convert a struct to a void[]?  I'm

 socket library in phobos and I want to send an aligned struct over the

 Here's the best solution I've come up with so far...

(&f)[0 .. 1] works just fine. Any array implicitly converts to void[].

Duh.. (/me smacks my head) of course. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Sep 09 2004
prev sibling parent Helmut Leitner <leitner hls.via.at> writes:
Vathix wrote:
 
 "mcl" <mcl_member pathlink.com> wrote in message
 news:chr0uj$rvk$1 digitaldaemon.com...
 I'm stuck.  What is the best way to convert a struct to a void[]?  I'm

 socket library in phobos and I want to send an aligned struct over the

 Here's the best solution I've come up with so far...

(&f)[0 .. 1] works just fine. Any array implicitly converts to void[].

Makes a nice FAQ entry: <http://www.wikiservice.at/wiki4d/wiki.cgi?FaqRoadmap#Howtoconverttovoid> -- Helmut Leitner leitner hls.via.at Graz, Austria www.hls-software.com
Sep 09 2004
prev sibling parent "Garett Bass" <gtbass studiotekne.com> writes:
"mcl" wrote:
 I'm using the socket library in phobos and I
 want to send an aligned struct over the network.

A word of warning... When sending structured data over the network, keep in mind the endianness of the client and server may (eventually) be different. For example, *if* there were a D compiler for non-x86-based platforms, such as the Mac, your struct could be sent from a Big-endian machine to a little-endian machine. This would FUBAR any float/double (and multibyte integer, I think) data you may have in your struct, since machines of different endianness interpret multibyte datatypes differently.
Sep 12 2004