Subject:
[ruby-ffi] Arrays in Structs and Unions
From:
Quintus
Date:
2/4/10 1:21 PM
To:
ruby-ffi

Hi,

I've two questions. This is the more important one: How to use arrays
in Structs via FFI? I have this nice struct declaration:
----------------------------------------------------
typedef struct _OSVERSIONINFO {
  DWORD dwOSVersionInfoSize;
  DWORD dwMajorVersion;
  DWORD dwMinorVersion;
  DWORD dwBuildNumber;
  DWORD dwPlatformId;
  TCHAR szCSDVersion[128];
} OSVERSIONINFO;
----------------------------------------------------
( From http://msdn.microsoft.com/en-us/library/ms724834%28VS.85%29.aspx
, to be used with the GetVersionInfoEx() function:
http://msdn.microsoft.com/en-us/library/ms724451%28VS.85%29.aspx )
and I'm not sure how to access the szCSDVVersion[128] member. I
thought, I had to work with Memory pointers for arrays, but the
following code doesn't work for me:
-----------------------------------------------------
class OSVersionInfo < FFI::Struct

  layout  :os_version_info_size, :int,
            :major_version, :int,
            :minor_version, :int,
            :build_number, :int,
            :platform_id, :int,
            :csdv_version, :buffer_out

end

ptr = FFI::MemoryPointer.new(:pointer, 128)
osversioninfo = OSVersionInfo.new
osversioninfo[:csdv_version] = ptr # line 106
osversioninfo[:os_version_info_size] = OSVersionInfo.size
get_version_ex(osversioninfo)
p osversioninfo[:major_version]
---------------------------------------------------------
I get this error:
---------------------------------------------------------
system_info.rb:106:in `put': put not supported for
FFI::StructLayout::Field (ArgumentError)
	from system_info.rb:106:in `[]='
	from system_info.rb:106:in `test_version'
	from system_info.rb:117:in `<main>'
---------------------------------------------------------
I tried it without the MemoryPointer:
---------------------------------------------------------
osversioninfo = OSVersionInfo.new
osversioninfo[:os_version_info_size] = OSVersionInfo.size
get_version_ex(osversioninfo)
p osversioninfo[:major_version] #=> 0
---------------------------------------------------------
That code doesn't thorw an error, but the function call fails - the
line starting with "p" should print out 6 on my Vista machine.
How can this be done?

The second question is a simple one: Where do I find a quick example
of how to use the FFI::Union class? The wiki just states this:
> The actual Windows INPUT struct contains an anonymous union member with MOUSEINPUT, KEYBDINPUT,
> and HARDWAREINPUT members. As the MOUSEINPUT struct is the largest of these members, we can get
> away with the hacky InputEvent FFI union definition for example purposes.
So, what to do if I haven't an "example purpose"?

ruby -v: ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-mingw32]
OS: Windows Vista SP2

Marvin