This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: More on revamping Win32API
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
A while back I talked about revamping the Win32API package. I've since made a couple of changes to how I'm going to approach things.
First, I'm going to add options that allow you to automatically generate constant names that match the function name in whatever namespace you like. For example, instead of doing this:
module Windows
module Path
PathAddBackslash = Win32API.new('shlwapi', 'PathAddBackslash', 'P', 'P')
PathAddExtension = Win32API.new('shlwapi', 'PathAddExtension', 'PP', 'I')
PathAppend = Win32API.new('shlwapi', 'PathAppend', 'PP', 'I')
end
end
You'll be able to do this:
module Windows
module Path
API.auto_constants = true
API.auto_namespace = 'Windows::Path'
API.new('PathAddBackslash', 'P', 'P', 'shlwapi')
API.new('PathAddExtension', 'PP', 'I', 'shlwapi')
API.new('PathAppend', 'PP', 'I')
end
end
While it may not seem like much from this small example, I literally have *hundreds* of these types of declarations in the windows-pr package. Since your average Windows function is about 12 characters long, the savings and convenience really starts to add up over time.
Things become more pronounced when you realize that there should be explicit declarations for the ANSI and Unicode versions of each function (where they exist) if we want to be thorough. So, our first example now looks like this:
Multiply that several hundred times and you *really* start to see how painful this can get. So, I'm going to add another global setting that automatically defines those for you if you want, making this code the equivalent:
module Windows
module Path
API.auto_constants = true
API.auto_namespace = 'Windows::Path'
API.auto_unicode = true
API.new('PathAddBackslash', 'P', 'P', 'shlwapi')
API.new('PathAddExtension', 'PP', 'I', 'shlwapi')
API.new('PathAppend', 'PP', 'I')
end
end
Last but not least is the practice of defining methods that are identical to the function names so you can avoid the '.call' and not have to check return values explicitly. Here's a snippet of the approach I'm currently using:
module Windows
module Path
PathAddBackslash = Win32API.new('shlwapi', 'PathAddBackslash', 'P', 'P')
PathAddExtension = Win32API.new('shlwapi', 'PathAddExtension', 'PP', 'I')
PathAppend = Win32API.new('shlwapi', 'PathAppend', 'PP', 'I')
def PathAddBackslash(path)
PathAddBackslash.call(path)
end
def PathAddExtension(path, ext)
PathAddExtension.call(path, ext) != 0 # BOOL method
end
def PathAppend(path, more)
PathAppend.call(path, more) != 0 # BOOL method
end
end
end
I'm going to add yet another global setting that automatically defines these methods for you. If the function is tagged as a boolean (an optional 5th argument), then it will also get the "!= 0" bit added to it. So, the above example (which doesn't even include the explicit ANSI and Unicode definitions) can be reduced to this:
module Windows
module Path
API.auto_constants = true
API.auto_namespace = 'Windows::Path'
API.auto_methods = true
API.new('PathAddBackslash', 'P', 'P', 'shlwapi')
API.new('PathAddExtension', 'PP', 'I', 'shlwapi', true)
API.new('PathAppend', 'PP', 'I', true)
end
end
Plus, if you add API.auto_unicode = true, it's now a 3-for-1. Mega savings.
The question I'm debating now is whether I should make this a stand in replacement for Win32API (with the hope of making it core) or just write a wrapper around Win32API.