在Ruby中方便的调用Win32 API (使用windows-pr和CStruct)

原文网址: http://www.w-yong.com/docs/ruby_win32_api.html

在Ruby中方便的调用Win32 API (使用windows-pr和CStruct)


缘由

平时工作中,我主要使用C/C++和Ruby。有时经常需要调用API来写一些工具,但又不想动用重量级的C/C++.这时就想到了用Ruby来写。话说Ruby,确实是程序员的好帮手,方便,快捷。是居家旅行......的必备良药。


在Ruby中有一个Win32API,是用来调用API的。但是用起来略为有点啰嗦和冗长。还好,RubyForge上有个Win32 Utils项目,专门提供了对API调用的封装,使得调用API更方便了一步。而且,Win32 Utils已经分门别类的封装好了很多Windows的功能模块,可以直接使用。如win32-file,win32-dir等。


但是,有两个原因导致了Win32APIWin32 Utils在使用上的不方便:

  1. 不管是Win32API还是Win32Utils,虽然解决了调用API的问题,没有很好的解决结构体参数的问题。我们知道,Windows的很多API大都需要结构体指针的参数,来传入或是传出信息。使用者大多利用String#unpack和Array#pack来处理。

  2. Win32 Utils提供的封装好的功能模块,如:win32-file,win32-dir等,是对API的进一步封装,将API封装在底下。这样一来,如果想直接利用API来写程序的话,这些模块暂时就用不上了。

鉴于此,我的经验是使用  windows-pr  CStruct  来调用Windows的API.使用起来比较直观。下面进行分别介绍:

windows-pr

概述

Win32Utils中有3个十分重要的gem:  win32-api, windows-api, windows-pr.其他的功能模块都是基于这三个之上。我们来说说这三个的关系:
  • win32-api

    封装了对API的调用。主要就是一个dll: api.so

  • windows-api

    对上面的 win32-api进行了简单包装,使得使用更简单一些。

  • windows-pr

    依赖与上面两个,定义了大量的Win32的API和常量,免去了我们自己定义函数的麻烦。当然,也有一些API没有封装,还得需要我们自己动手。

安装

windows-pr的安装很简单:
gem install windows-pr
但是,如果你用的是ruby1.9.x,则需要特别注意:安装windows-pr时,同时会安装 win32-api,默认的情况会安装:win32-api-1.4.6-x86-mingw32。但这个gem是基于ruby1.8.x的,所以在Ruby1.9.x上不能正确运行。 
解决方案如下:
  1. 安装windows-pr: gem install windows-pr

    这一步,会给你安装3个gem:windows-pr,windows-api 和win32-api-1.4.6-x86-mingw32(win32-api当前版本是:1.4.6)

  2. 安装DevKit

    按照官方的步骤来,很简单。DevKit主要就是用来编译Ruby本地扩展的。
  3. 安装win32-api:gem install win32-api --platform=ruby

    这一步,会安装gem:win32-api-1.4.6,并生成新的api.so

  4. 用win32-api-1.4.6的api.so替换掉win32-api-1.4.6-x86-mingw32中的api.so。
还有一个偷懒的办法,这里有一个编译好的适合ruby1.9.x的 api.so,请下载下来,在执行完第一步之后,直接进行第4步,替换掉api.so即可。如果仍然不好用,则还需要你亲自编译一下。

使用

实际上,Win32Utils封装的windows的各个功能模块就是使用windows-pr的例子,有兴趣的,可以看看。大家对Win32Utils也比较熟悉,这里就不过多介绍了。

CStruct

概述

CStruct是Ruby 语言用来模仿 C 语言结构体。 有过Win32开发经验的童鞋们一定都知道,Win32SDK中,大部分的API都需要有结构体指针作参数。例如: void GlobalMemoryStatus(LPMEMORYSTATUSlpBuffer);


Ruby基本的二进制操作主要是利用String#pack和Array#unpack来进行。但是,如果来处理C语言中的结构体就有些冗长啰嗦了。如何能模拟C语言中的结构体呢? CStruct就是来做这个事情的。(注意:此CStruct并不是 DL模块中的CStruct!)

这里只是大体介绍一下CStruct。更多的信息及示例,请看CStruct项目的主页.

安装

CStruct的安装也很简单:
gem install cstruct

CStruct的基本用法

先看一个C语言的结构体Point:
struct  Point
{
  int  x;
  int  y;
};
使用CStruct在Ruby中模拟结构体 Point:
class  Point  CStruct
    int32 :x
    int32 :y
end
看起来是比较直观。看看Point的简单用法,来自CStruct的主页。
require  'cstruct'
# struct Point inRuby: 
class  Point  CStruct
    int32 :x
    int32 :y 
end

# create a Point'sinstance
point =  Point.new

# assign like as Clanguage
point.x =  10
point.y =  20
puts  "point.x = #{point.x},point.y =#{point.y}"

CStruct提供了几个方法,用于取得结构体相关的信息,如(仅列出常用的):
  • 类方法:size,__size__
    取得结构体的大小。另:__size__ 是size的一个别名.

  • 实例方法:<<

    给结构体实例赋值。
  • 实例方法:data

    返回结构体实例的内部存储buffer.这个方法在调用api时经常用到。

Win32Struct

Win32Struct是CStruct带的一个对常用的win32数据类型的封装。在定义windows结构体时,主要用它。使用的时候,需要require。.
require 'win32struct'
                        
Win32中的MEMORYSTATUS 的定义基本如下面这个样子:
struct  MEMORYSTATUS{ 
    DWORD dwLength;
    DWORD dwMemoryLoad;
    DWORD dwTotalPhys;
    DWORD dwAvailPhys;
    DWORD dwTotalPageFile;
    DWORD dwAvailPageFile;
    DWORD dwTotalVirtual;
    DWORD dwAvailVirtual;
} ;
使用Win32Struct在Ruby中模拟结构体 MEMORYSTATUS:
class  MEMORYSTATUS  Win32Struct
      DWORD  :dwLength
      DWORD  :dwMemoryLoad
      DWORD  :dwTotalPhys
      DWORD  :dwAvailPhys
      DWORD  :dwTotalPageFile
      DWORD  :dwAvailPageFile
      DWORD  :dwTotalVirtual
      DWORD  :dwAvailVirtual
end
是不是挺像C语言的结构体?

windows-pr & CStruct

有了 windows-prCStruct,我们就可以很直观的直接调用API了。来看一个具体的例子:GlobalMemoryStatus(获取系统的内存状态)。
# CStruct Examples
require 'windows/memory'
require 'win32struct'

include Windows::Memory

# example:

# typedef struct _MEMORYSTATUS {
#     DWORD dwLength;
#     DWORD dwMemoryLoad;
#     DWORD dwTotalPhys;
#     DWORD dwAvailPhys;
#     DWORD dwTotalPageFile;
#     DWORD dwAvailPageFile;
#     DWORD dwTotalVirtual;
#     DWORD dwAvailVirtual;
# } MEMORYSTATUS, *LPMEMORYSTATUS;

class MEMORYSTATUS < Win32Struct
    DWORD :dwLength
    DWORD :dwMemoryLoad
    DWORD :dwTotalPhys
    DWORD :dwAvailPhys
    DWORD :dwTotalPageFile
    DWORD :dwAvailPageFile
    DWORD :dwTotalVirtual
    DWORD :dwAvailVirtual        
end

# create a MEMORYSTATUS's instance
stat = MEMORYSTATUS.new {|st| st.dwLength = MEMORYSTATUS.size }

# call API "GlobalMemoryStatus" - See also MSDN
GlobalMemoryStatus(stat.data)

#output
printf "[Physical Memory]\n"
printf "  total:d bytes\n",stat.dwTotalPhys
printf "  free :d bytes\n",stat.dwAvailPhys

printf "[Virtual Memory]\n"
printf "  total:d bytes\n",stat.dwTotalVirtual
printf "  free :d bytes\n",stat.dwAvailVirtual

printf "[Paging File]\n"
printf "  total:d bytes\n",stat.dwTotalPageFile
printf "  free :d bytes\n",stat.dwAvailPageFile

上面的示例代码,像是用C直接调用API一样直观。免去了自己大量的pack,unpack。CStruct还有其他Win32的例子,比如: 列举所有进程, 获取系统信息等, 获取系统版本等,有兴趣的可以看看。

结束

本文到这里也就结束了,文本给出了在ruby中使用windows api的一个方便直观的方法。当然,CStruct目前还有一点限制,比如:多维数组(CStruct目前只支持一维数组)和位域暂时还不支持。总的来说,windows-pr和CStruct结合使用,还是比较方便的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值