kejohm has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I am wondering if there is any way to write data to a C structure in memory, knowing the address of the structure, using only Perl functions, modules, etc.

I am creating a GUI application using Win32::GUI and using a Listbox control which is to be owner-drawn. In order to get this to work, I need to handle the WM_MEASUREITEM message, among others. Since Win32::GUI doesn't have an event for this message, I need to create a hook. The message receives a pointer to a structure, which needs to be filled out with the desired item height.

I know how to use pack() and unpack() to access the data in the structure but I am unsure how to store the information back in the same structure. I have tried packing the data back into the argument passed to the sub (using @_) but this didn't seem to work. I also tried it with Inline::C, but the module seems to have a problem with directories with spaces in the names. The reason I would like to be able to do this with only Perl functions or core modules is that I will most likely distribute this app as a sample with a module I am creating and would like to keep the dependencies to a minimum.

Does anyone have any suggestions about getting this to work?

Here is my hook code:

$winMain->Hook( WM_MEASUREITEM, sub { my($self, $wParam, $lParam, $type, $msgcode) = @_; return 1 unless $type == 0; return 1 unless $msgcode == WM_MEASUREITEM; my %measureitem; # Unpack data from structure @measureitem{qw(CtrlType CtrlID itemID itemWidth itemHeight it +emData)} = unpack 'IIIIIL', unpack 'P24', pack 'L', $lParam; # Set the height of the items $measureitem{'itemHeight'} = 30; # Pack data back into structure my $struct = pack 'IIIIIL', @measureitem{qw(CtrlType CtrlID itemID itemWidth itemHeigh +t itemData)}; $lParam = unpack 'L', pack 'P24', $struct; # or #$_[2] = unpack 'L', pack 'P24', $struct; return 1; }, );

Here is a sample of how it would be done in C:

case WM_MEASUREITEM: lpmis = (LPMEASUREITEMSTRUCT) lParam; // Set the height of the list box items. lpmis->itemHeight = 30; return true;

Thanks in advance for any help.

Replies are listed 'Best First'.
Re: Manipulating C Structures using only Perl
by chromatic (Archbishop) on Aug 17, 2010 at 16:39 UTC
      The OP's problem is not in packing or unpacking the structure, the problem is in coping the packed structure to a specific memory address.
Re: Manipulating C Structures using only Perl
by JavaFan (Canon) on Aug 17, 2010 at 12:18 UTC
    I am wondering if there is any way to write data to a C structure in memory, knowing the address of the structure, using only Perl functions, modules, etc.
    I don't think Perl-only functions allow you to write to arbitrary memory locations. You'd need XS for that.
      I don't think Perl-only functions allow you to write to arbitrary memory locations. You'd need XS for that.

      like PeekPoke or Win32::API

Re: Manipulating C Structures using only Perl
by kejohm (Hermit) on Aug 18, 2010 at 08:21 UTC

    Thanks to those monks who replied. I've decided I might just write a small amount of XS code, build as a DLL and distribute it with my app. This seems like the best way of doing it, unless other Monks post any other suggestions.