www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A little direction, if anyone is so inclined...

reply Chris Stevenson <Chris_member pathlink.com> writes:
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
Aug 15 2004
next sibling parent reply "antiAlias" <gblazzer corneleus.com> writes:
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

 window.  It contains ushorts, uints, and wchars.  Unfortunatly, the

 elements can vary in length, and possibly not be present at all.  (I put

 rundown in a previous post.)  I decided to try to make with work with a

 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,

 #      temp = cast(ubyte*)&num;
 #      storage ~= temp[0..num.sizeof];
 #      printf("storage.length = %d, storage = %s", storage.length,

 #      return 0;
 #}

 It compiles just fine, but I get an access violation on the (first)

 After a bit of reading through Phobos, I'm thinking that I need to use

 specifically a memory stream.  Could anyone point me to a primer--I've

 worked with streams much besides cout.

 Thanks,
 Chris Stevenson

Aug 15 2004
parent reply Chris Stevenson <Chris_member pathlink.com> writes:
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
Aug 15 2004
parent reply Nick <Nick_member pathlink.com> writes:
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
Aug 15 2004
parent Chris Stevenson <Chris_member pathlink.com> writes:
#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); } }
Aug 16 2004
prev sibling parent reply pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
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
Aug 15 2004
parent Deja Augustine <Deja_member pathlink.com> writes:
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
Aug 15 2004