使用 Ruby 来调用 Windows DLL 函数

正好项目中要使用外部的 DLL 接口,如果用 C 来写固然是可以的。
但是也好多年没用了,觉得再拿起来也要些时间。就搜了下 Ruby 来怎么对接。

基本上网上推荐了2种方法:

  • fiddle
  • ffi

fiddleRuby 标准库自带的,用法比较简单,但是官方文档特别少。
ffi 是一个独立的 Gem,他是基于 libffi 的一个外部扩展来实现的,官网文档比较多。

感觉 fiddle 使用比较简单,我用的 DLL 也不是很复杂,就只试了 fiddle
首先推荐看下这篇基础教程 ,大体就知道怎么用了。

但是很快就遇到了一个问题,int[] 这种数组怎么传过去。
搜了下,看到了这篇文章,试了一下用 a.pack('i' * a.size) 方法的确可以。

遇到的第二个问题是如何传 UNICODE 字符串,搜了一下没有搜到。
于是我就想说不定 ffi 这边的文档会有些提示。
果然官方Wiki 里有一篇例子讲到了,使用需要encode('UTF-16LE')一下,
有一点我试的时候不在末尾加 \0 也是没问题的。

message_box.rbview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require 'fiddle'
require 'fiddle/import'
require 'fiddle/types'

module User32
extend Fiddle::Importer

dlload 'user32'

include Fiddle::Win32Types # 增加一些常用的typealias
typealias 'LPCTSTR', 'char*'

extern 'int MessageBoxW(HWND, LPCTSTR, LPCTSTR, UINT)'
end

msg = 'Hello 你好'.encode('UTF-16LE')
User32.MessageBoxW(0, msg, msg, 0)