如何从Ruby调用Windows DLL函数?

17

我想使用Ruby访问DLL中的函数。我希望在保留编写Ruby代码简易性的同时,使用C的低级访问。我该如何实现?

4个回答

15

可以看看 Win32API 标准库。它是 Windows 32 API 或 DLLs 的一个相当简单(但晦涩)的接口。

这里有文档这里有一些例子。以下是其中的一个示例:

require "Win32API"    
def get_computer_name
  name = " " * 128
  size = "128"
  Win32API.new('kernel32', 'GetComputerName', ['P', 'P'], 'I').call(name, size)  
  name.unpack("A*")  
end 

4
它的表现相当不错,除非您的DLL具有Win32API无法处理的参数(例如双精度)。那时,您将进入“Array.unpack噩梦”。 - SztupY
3
Win32API和文档链接已失效。 - zeboidlund
2
以下是Win32API文档的更新链接:Ruby 1.8.7 | Ruby 1.9.2 | Ruby 2.0.0 - Br.Bill

9
您可以使用Fiddle:http://ruby-doc.org/stdlib-2.0.0/libdoc/fiddle/rdoc/Fiddle.html Fiddle是一个鲜为人知的模块,自1.9.x版本起被添加到Ruby的标准库中。它允许您直接从Ruby与C库进行交互。
它通过包装libffi工作,后者是一种流行的C库,允许在一个语言中编写的代码调用在另一种语言中编写的方法。如果您还没有听说过它,“ffi”代表“foreign function interface”。而且您不仅限于使用C。一旦您学会了Fiddle,您可以使用Rust和其他支持它的语言编写的库。 http://blog.honeybadger.io/use-any-c-library-from-ruby-via-fiddle-the-ruby-standard-librarys-best-kept-secret/
require 'fiddle'

libm = Fiddle.dlopen('/lib/libm.so.6')

floor = Fiddle::Function.new(
  libm['floor'],
  [Fiddle::TYPE_DOUBLE],
  Fiddle::TYPE_DOUBLE
)

puts floor.call(3.14159) #=> 3.0

或者

require 'fiddle'
require 'fiddle/import'

module Logs
  extend Fiddle::Importer
  dlload '/usr/lib/libSystem.dylib'
  extern 'double log(double)'
  extern 'double log10(double)'
  extern 'double log2(double)'
end

# We can call the external functions as if they were ruby methods!
puts Logs.log(10)   # 2.302585092994046
puts Logs.log10(10) # 1.0
puts Logs.log2(10)  # 3.321928094887362

6

3

这里有一个开源的win32-api,由Hiroshi Hatake和Daniel Berger创建,是Win32API的替代品。它适用于Ruby 1.8、1.9和2.X版本。


2
看起来它还没有完全死亡...在2017年仍在更新。 - aidan
它在2020年仍在使用中...但当前的作者建议转移到FFI。 - Br.Bill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接