Ruby FFI - Ruby调用C库最棒的工具
来源:互联网 发布:淘宝有些不能发图评价 编辑:程序博客网 时间:2024/06/05 19:13
Ruby FFI - Ruby调用C库最棒的工具
2008-11-02 00:40 by 见习编辑 robbin 评论(6) 有4162人浏览
Ruby C++ C C#
声明:ITeye资讯文章的版权属于ITeye网站所有,严禁任何网站转载本文,否则必将追究法律责任!
北京: ITeye网站诚聘产品交互设计
猎头职位: Ruby解析器的性能一向被人垢病,很多性能敏感的程序,都必须用C语言来编写,然后使用Ruby去调用C库。但糟糕的是,Ruby调用C库并不是一件轻松的活,需要你对Ruby的内部数据结构有比较深入的了解,甚至需要你仔细阅读Ruby相关的源代码,然后用C语言编程作为黏合剂,用Ruby特有的C API去给外部的C库增加一层封装。
以上的过程,相当于你要打开Ruby解析器的内部进行API调用了,对程序员的要求很高。而且一旦Ruby内部的数据结构随着版本升级发生变动,你的这些黏合剂程序就必须重写。比方说现在Ruby 1.9出来以后,绝大部分Ruby的C扩展库统统无法正常编译。
基于以上这些原因,给Ruby写C的扩展库一件非常痛苦的事情,而且也是Ruby社区程序员一直抱怨的问题之一。然而随着FFI的出现,我们即将告别这些痛苦的历史!
FFI即Foreign Function Interface,外部函数调用接口,并非Ruby独有的概念,只不过因为Ruby扩展库带来的痛苦,使得Ruby的FFI显得格外迫切。FFI最早已经在Rubinius虚拟机平台上实现了,随后在JRuby上面也得以实现,而今天:2008年11月1日,在Ruby官方版本的解析器Ruby 1.8.6/1.8.7和1.9版本上也可以使用FFI了。
安装FFI很简单:
使用FFI也很简单,比方说调用C语言标准库的printf函数,我们可以这样来写:
用attach_fuction就可以把C语言标准库的printf函数绑定到ruby里面来了,后面的参数分别声明C函数的传入参数和返回值。如果需要引入其他C库,可以预先使用ffi_lib指定库的名称。(我使用ffi_lib未能绑定非标准库,有可能是FFI的bug?也有可能是我没有设置对?)
有了FFI,在Ruby语言里面调用C库,就变成了一件异常轻松的事情,完全不需要ruby程序员再去吭哧吭哧啃C语言了,只要你手里捧着C库的API手册能看清楚函数的参数定义就够用了,然后你就可以直接在ruby里面随心所欲的调用它了,在调用之前,只需要用attach_function进行一次函数绑定声明即可。这对于整个ruby社区来说是一件非常棒的好消息。
在FFI的源代码树的samples目录下面还有几个小例子,大家可以自己看看:http://kenai.com/projects/ruby-ffi/sources/723/show
作为一个对比,我们来看看传统的ruby扩展库是如何调用C库的吧。以上面的为例,如果我们希望在ruby里面使用C库的printf函数,那么要先用ruby API的格式来写一段C代码去封装它:
当然你必须对ruby.h里面定义的ruby内部数据结构和ruby内部的函数调用有充分的了解。然后你要创建一个extconf.rb文件:
运行这个文件:ruby extconf.rb,会创建出来编译这段C代码的Makefile,然后你再编译和安装,最终这个共享链接库会被拷贝到你的ruby的本地扩展库目录下面。最后你才可以在ruby里面调用这个封装好的dummy_printf方法。
另外,对于通过FFI去调用比较复杂的C库的时候,会涉及到不同语言之间的数据类型转换问题,关于数据类型的对照表,以及FFI使用更详细的介绍请看张驰原(他也是rmmseg的作者)的文章:http://pluskid.lifegoo.com/?p=370
以上的过程,相当于你要打开Ruby解析器的内部进行API调用了,对程序员的要求很高。而且一旦Ruby内部的数据结构随着版本升级发生变动,你的这些黏合剂程序就必须重写。比方说现在Ruby 1.9出来以后,绝大部分Ruby的C扩展库统统无法正常编译。
基于以上这些原因,给Ruby写C的扩展库一件非常痛苦的事情,而且也是Ruby社区程序员一直抱怨的问题之一。然而随着FFI的出现,我们即将告别这些痛苦的历史!
FFI即Foreign Function Interface,外部函数调用接口,并非Ruby独有的概念,只不过因为Ruby扩展库带来的痛苦,使得Ruby的FFI显得格外迫切。FFI最早已经在Rubinius虚拟机平台上实现了,随后在JRuby上面也得以实现,而今天:2008年11月1日,在Ruby官方版本的解析器Ruby 1.8.6/1.8.7和1.9版本上也可以使用FFI了。
安装FFI很简单:
- gem install ffi
使用FFI也很简单,比方说调用C语言标准库的printf函数,我们可以这样来写:
- require 'ffi'
- module MyExtModule
- extend FFI::Library
- attach_function :printf, [:string], :void
- end
- MyExtModule.printf("Hello FFI\n")
用attach_fuction就可以把C语言标准库的printf函数绑定到ruby里面来了,后面的参数分别声明C函数的传入参数和返回值。如果需要引入其他C库,可以预先使用ffi_lib指定库的名称。(我使用ffi_lib未能绑定非标准库,有可能是FFI的bug?也有可能是我没有设置对?)
有了FFI,在Ruby语言里面调用C库,就变成了一件异常轻松的事情,完全不需要ruby程序员再去吭哧吭哧啃C语言了,只要你手里捧着C库的API手册能看清楚函数的参数定义就够用了,然后你就可以直接在ruby里面随心所欲的调用它了,在调用之前,只需要用attach_function进行一次函数绑定声明即可。这对于整个ruby社区来说是一件非常棒的好消息。
在FFI的源代码树的samples目录下面还有几个小例子,大家可以自己看看:http://kenai.com/projects/ruby-ffi/sources/723/show
作为一个对比,我们来看看传统的ruby扩展库是如何调用C库的吧。以上面的为例,如果我们希望在ruby里面使用C库的printf函数,那么要先用ruby API的格式来写一段C代码去封装它:
- #include <ruby.h>
- static VALUE
- dummy_printf(VALUE self, VALUE format, VALUE num)
- {
- int rlt = printf(RSTRING_PTR(format), NUM2INT(num));
- return INT2FIX(rlt);
- }
- void Init_printf()
- {
- /* register the method to the Kernel module */
- rb_define_method(rb_mKernel, "dummy_printf",
- RUBY_METHOD_FUNC(dummy_printf), 2);
- }
当然你必须对ruby.h里面定义的ruby内部数据结构和ruby内部的函数调用有充分的了解。然后你要创建一个extconf.rb文件:
- require 'mkmf'
- create_makefile('printf')
运行这个文件:ruby extconf.rb,会创建出来编译这段C代码的Makefile,然后你再编译和安装,最终这个共享链接库会被拷贝到你的ruby的本地扩展库目录下面。最后你才可以在ruby里面调用这个封装好的dummy_printf方法。
另外,对于通过FFI去调用比较复杂的C库的时候,会涉及到不同语言之间的数据类型转换问题,关于数据类型的对照表,以及FFI使用更详细的介绍请看张驰原(他也是rmmseg的作者)的文章:http://pluskid.lifegoo.com/?p=370
- Ruby FFI - Ruby调用C库最棒的工具
- Ruby的调用机制
- C代码中调用Ruby
- ruby版的cat工具
- ruby 方法之间的调用
- FFI Library (lua 调用 c)
- [Ruby] ruby中的拟态方法的调用中的小细节
- node ffi调用C、C++动态库出现的问题
- ruby 操作剪切板和gem install ffi 问题
- ruby
- ruby
- ruby
- Ruby
- Ruby
- Ruby
- ruby
- ruby
- ruby
- boost之spirit学习-mini_c(3)
- syn flood attack
- Android学习总结目录
- 二叉树递归创建遍历
- 2012-3-22日总结
- Ruby FFI - Ruby调用C库最棒的工具
- 表的有关操作
- TortoiseSVN搭建本地版本库及简单操作使用
- ObjectiveC中的赋值,对象拷贝,浅拷贝与深拷贝(续)
- php Static的用法
- 日常使用linux命令----随手翻
- CSS a 控制超链接文字样式
- 正则匹配
- 学习笔记——JAAS