Thread overview
A little direction, if anyone is so inclined...
Aug 16, 2004
Chris Stevenson
Aug 16, 2004
antiAlias
Aug 16, 2004
Chris Stevenson
Aug 16, 2004
Nick
Aug 16, 2004
Chris Stevenson
Aug 16, 2004
pragma
Aug 16, 2004
Deja Augustine
August 16, 2004
I'm trying to create a block of memory to pass to a Windows function (LoadMenuIndirect, in winuser.h).  This chuck of memory defines the menu for the window.  It contains ushorts, uints, and wchars.  Unfortunatly, the different elements can vary in length, and possibly not be present at all.  (I put the rundown in a previous post.)  I decided to try to make with work with a dynamic array of ubytes like this:

#import std.c.stdio;
#int main()
#{
#      ubyte[] storage;
#      ubyte*  temp;
#      char[]  text;
#      int    num;
#
#      text = "&File\0";
#      num  = 40001;
#
#      storage ~= cast(ubyte[])text;
#      printf("storage.length = %d, storage = %s", storage.length, storage);
#      temp = cast(ubyte*)#
#      storage ~= temp[0..num.sizeof];
#      printf("storage.length = %d, storage = %s", storage.length, storage);
#      return 0;
#}

It compiles just fine, but I get an access violation on the (first) printf(). After a bit of reading through Phobos, I'm thinking that I need to use streams, specifically a memory stream.  Could anyone point me to a primer--I've never worked with streams much besides cout.

Thanks,
Chris Stevenson


August 16, 2004
You need a "%.*s" instead of "%s" in the printf() call. Also, you might take a look at the OutBuffer module instead of Stream: it's lighter.


"Chris Stevenson" <Chris_member@pathlink.com> wrote in message news:cfp04j$1bfu$1@digitaldaemon.com...
> I'm trying to create a block of memory to pass to a Windows function (LoadMenuIndirect, in winuser.h).  This chuck of memory defines the menu
for the
> window.  It contains ushorts, uints, and wchars.  Unfortunatly, the
different
> elements can vary in length, and possibly not be present at all.  (I put
the
> rundown in a previous post.)  I decided to try to make with work with a
dynamic
> array of ubytes like this:
>
> #import std.c.stdio;
> #int main()
> #{
> #      ubyte[] storage;
> #      ubyte*  temp;
> #      char[]  text;
> #      int    num;
> #
> #      text = "&File\0";
> #      num  = 40001;
> #
> #      storage ~= cast(ubyte[])text;
> #      printf("storage.length = %d, storage = %s", storage.length,
storage);
> #      temp = cast(ubyte*)&num;
> #      storage ~= temp[0..num.sizeof];
> #      printf("storage.length = %d, storage = %s", storage.length,
storage);
> #      return 0;
> #}
>
> It compiles just fine, but I get an access violation on the (first)
printf().
> After a bit of reading through Phobos, I'm thinking that I need to use
streams,
> specifically a memory stream.  Could anyone point me to a primer--I've
never
> worked with streams much besides cout.
>
> Thanks,
> Chris Stevenson
>
>


August 16, 2004
Okay, you've narrowed the problem down to the first printf:

>#      printf("storage.length = %d, storage = %s", storage.length, storage);

You're really close to doing this correctly, its just that D has one wrinkle when using strings and printf.  Use "%.*s" instead of "%s" when printing strings in printf, or just use writef instead (with the usual "%s" formatter).

- Pragma




August 16, 2004
In article <cfp0kp$1bou$1@digitaldaemon.com>, antiAlias says...
>
>You need a "%.*s" instead of "%s" in the printf() call. Also, you might take a look at the OutBuffer module instead of Stream: it's lighter.
>

OutBuffer. Cool. Thanks for pointing that out!

Next question:
std.outiffer.toBytes() returns a dynamic array of ubytes.
LoadMenuIndirect takes a pointer. (The data in the array indicates the last
element, with a special flag.)

Can I do this?

#ubyte* buildMenu()
#{
#   outBuffer  myBuffer;
#// do stuff to fill up buffer
#   return myBuffer.toBytes;
#}

Also:
Hmm... I'll need to subclass OutBuffer, to add support for wchars. (yay
Windows...)  Would this be all I have to do?

#MyOutBuffer : OutBuffer
#{
#    this() {super()}
#    void write(wchar[] s)
#    {
#         write(cast(ubyte[])s);
#    }
#}

Thanks,

--Chris


August 16, 2004
In article <cfp3cd$1dfr$1@digitaldaemon.com>, Chris Stevenson says...
>
>OutBuffer. Cool. Thanks for pointing that out!
>
>Can I do this?
>
>#ubyte* buildMenu()
>#{
>#   outBuffer  myBuffer;
>#// do stuff to fill up buffer
>#   return myBuffer.toBytes;
>#}

Almost! In D, arrays are not automatically pointers. But you can write

return &myBuffer.toBytes[0];

and it should work. But remember the [0], or it won't work correctly (and probably won't compile, IIRC.)

>#MyOutBuffer : OutBuffer
>#{
>#    this() {super()}
>#    void write(wchar[] s)
>#    {
>#         write(cast(ubyte[])s);
>#    }
>#}

You have to include the line

alias OutBuffer.write write;

Since you override write(), you also remove OutBuffer.write from scope (don't
ask ;-). Also, you can drop the this() since OutBuffer.this() is called anyway.

Nick


August 16, 2004
In article <cfp1f0$1cen$1@digitaldaemon.com>, pragma <EricAnderton at yahoo dot com> says...
>
>
>Okay, you've narrowed the problem down to the first printf:
>
>>#      printf("storage.length = %d, storage = %s", storage.length, storage);
>
>You're really close to doing this correctly, its just that D has one wrinkle when using strings and printf.  Use "%.*s" instead of "%s" when printing strings in printf, or just use writef instead (with the usual "%s" formatter).
>
>- Pragma
>
>
>
>

The reason for that wrinkle, in case you're curious, is because arrays in D are actually represented in memory like the following structure:

struct array
{
int32 length;
void* data;
}

and that's exactly what the %.*s parameter expects, a length followed by a pointer to the data.

-Déja


August 16, 2004
>>#MyOutBuffer : OutBuffer
>>#{
>>#    this() {super()}
>>#    void write(wchar[] s)
>>#    {
>>#         write(cast(ubyte[])s);
>>#    }
>>#}
>
>You have to include the line
>
>alias OutBuffer.write write;
>

I was compiling with the -c flag, to check my syntax, and the compiler finally accepted this without complaint.  I'm just wondering, if I extended OutBuffer Correctly:

struct MenuExTemplateHeader
{
WORD    wVersion;
WORD    wOffset;
DWORD   dwHelpId;
}

struct MenuExTemplateItem
{
align(4)
{
DWORD    dwType;
DWORD    dwState;
UINT     uId;
}
align(2)
{
WORD     bResInfo;
}
// WCHAR[]  szText;     //these are variable, so
// DWORD    dwHelpId;   //in D, these must be seperate from struct;
}

class MenuBuffer : OutBuffer
{
alias OutBuffer.write write;
alias OutBuffer.align2 align2;
alias OutBuffer.align4 align4;

void write(wchar[] s)
{
this.write(cast(ubyte[])s);
}

void write(MenuExTemplateHeader h)
{
this.write(h.wVersion);
this.write(h.wOffset);
this.write(h.dwHelpId);
}

void write(MenuExTemplateItem i)
{
this.align4();
this.write(i.dwType);
this.write(i.dwState);
this.write(i.uId);
this.align2();
this.write(i.bResInfo);
}
}