CSC/ECE 517 Fall 2013/ch1 1w21 w: Difference between revisions
(33 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== '''Ruby libraries to load objects of other languages at run time''' == | == '''Ruby libraries to load objects of other languages at run time''' == | ||
This is an advanced topic. Libraries are being developed where Ruby gems can load libraries (and even native code) of other languages.A few open-source projects like FFI are currently working on this. | This is an advanced topic. Libraries are being developed where Ruby gems can load libraries (and even native code) of other languages.A few open-source projects like FFI are currently working on this. | ||
__TOC__ | |||
==Introduction== | ==Introduction== | ||
==Runtime Library== | ===Runtime Library=== | ||
In computer programming, a runtime library is the API used by a compiler to invoke some of the behaviors of a runtime system. The runtime system implements the execution model and other fundamental behaviors of a programming language. The compiler inserts calls to the runtime library into the executable binary. During execution (run time) of that computer program, execution of those calls to the runtime library cause communication between the application and the runtime system. This often includes functions for input and output, or for memory management. | In computer programming, a runtime library is the API used by a compiler to invoke some of the behaviors of a runtime system. The runtime system implements the execution model and other fundamental behaviors of a programming language. The compiler inserts calls to the runtime library into the executable binary. During execution (run time) of that computer program, execution of those calls to the runtime library cause communication between the application and the runtime system. This often includes functions for input and output, or for memory management. | ||
The runtime library may implement a portion of the runtime system's behavior, but if one reads the code of the calls available, they typically are thin wrappers that simply package information and send it to the runtime system. However, sometimes the term runtime library is meant to include the code of the runtime system itself, even though much of that code cannot be directly reached via a library call. | The runtime library may implement a portion of the runtime system's behavior, but if one reads the code of the calls available, they typically are thin wrappers that simply package information and send it to the runtime system. However, sometimes the term runtime library is meant to include the code of the runtime system itself, even though much of that code cannot be directly reached via a library call. | ||
Line 14: | Line 15: | ||
===libffi=== | ===libffi=== | ||
FFI stands for Foreign Function Interface. A foreign function interface is the popular name for the interface that allows code written in one language to call code written in another language. The libffi library really only provides the lowest, machine dependent layer of a fully featured foreign function interface. A layer must exist above libffi that handles type conversions for values passed between the two languages. | FFI stands for Foreign Function Interface. A foreign function interface is the popular name for the interface that allows code written in one language to call code written in another language. The libffi library really only provides the lowest, machine dependent layer of a fully featured foreign function interface. A layer must exist above libffi that handles type conversions for values passed between the two languages.<ref>http://sourceware.org/libffi/</ref> | ||
libffi is a foreign function interface library. It provides a C programming language interface for calling natively compiled functions given information about the target function at run time instead of compile time. It also implements the opposite functionality: libffi can produce a pointer to a function that can accept and decode any combination of arguments defined at run time. | libffi is a foreign function interface library. It provides a C programming language interface for calling natively compiled functions given information about the target function at run time instead of compile time. It also implements the opposite functionality: libffi can produce a pointer to a function that can accept and decode any combination of arguments defined at run time. | ||
libffi is most often used as a bridging technology between compiled and interpreted language implementations. libffi may also be used to implement plug-ins, where the plug-in's function signatures are not known at the time of creating the host application. | libffi is most often used as a bridging technology between compiled and interpreted language implementations. libffi may also be used to implement plug-ins, where the plug-in's function signatures are not known at the time of creating the host application. | ||
Notable users include Python, Haskell, Dalvik, F-Script, PyPy, PyObjC, RubyCocoa, JRuby, Rubinius, MacRuby, gcj, GNU Smalltalk, IcedTea, Cycript, Pawn, Squeak, Java Native Access, Racket, | Notable users include Python, Haskell, Dalvik, F-Script, PyPy, PyObjC, RubyCocoa, JRuby, Rubinius, MacRuby, gcj, GNU Smalltalk, IcedTea, Cycript, Pawn, Squeak, Java Native Access, Racket,<ref>http://en.wikipedia.org/wiki/Libffi#cite_note-2</ref> Embeddable Common Lisp and Mozilla.<ref>http://en.wikipedia.org/wiki/Libffi#cite_note-3</ref> | ||
On Mac OS X libffi is commonly used with BridgeSupport, which provides programming language neutral descriptions of framework interfaces, and Nu which binds direct Objective-C access from Lisp. | On Mac OS X libffi is commonly used with BridgeSupport, which provides programming language neutral descriptions of framework interfaces, and Nu which binds direct Objective-C access from Lisp. | ||
libffi has been widely ported and is released under a MIT license. | libffi has been widely ported and is released under a MIT license. | ||
==How does it work?== | ==How does it work?<ref>http://www.rubyinside.com/ruby-ffi-library-calling-external-libraries-now-easier-1293.html</ref>== | ||
"One of the largest problems plaguing Ruby implementations [..] is the ever-painful story of "extensions". In general, these take the form of a dynamic library, usually written in C, that plugs into and calls Ruby's native API as exposed through ruby.h and libruby." | "One of the largest problems plaguing Ruby implementations [..] is the ever-painful story of "extensions". In general, these take the form of a dynamic library, usually written in C, that plugs into and calls Ruby's native API as exposed through ruby.h and libruby." | ||
Line 29: | Line 30: | ||
A basic demonstration of a Ruby script that uses C's getpid function should be enough to demonstrate the simplicity of FFI: | A basic demonstration of a Ruby script that uses C's getpid function should be enough to demonstrate the simplicity of FFI: | ||
<pre> | |||
require 'ffi' | require 'ffi' | ||
Line 38: | Line 39: | ||
puts GetPid.getpid | puts GetPid.getpid | ||
[[ | </pre> | ||
===Progress of FFI<ref>http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html</ref>=== | |||
One of the largest problems plaguing Ruby implementations is the ever-painful story of "extensions". In general, these take the form of a dynamic library, usually written in C, that plugs into and calls Ruby's native API as exposed through ruby.h and libruby. Ignoring for the moment the fact that this API exposes way more of Ruby's internals than it should, extensions present a very difficult problem for other implementations: | |||
Do we support them or not? | |||
In many cases, this question is answered for us; most extensions require access to object internals we can't expose, or can't expose without extremely expensive copying back and forth. But there's also a silver lining: the vast majority of C-based extensions exist solely to wrap another library. | |||
Isn't it obvious what's needed here? | |||
This problem has been tackled by a number of libraries on a number of platforms. On the JVM, there's Java Native Access (JNA). On Python, there's ctypes. And even on Ruby, there's the "dl" stdlib, wrapping libdl for programmatic access to dynamic libraries. But dl is not widely used, because of real or perceived bugs and a rather arcane API. Something better is needed. | |||
Wayne is one of the primary maintainers of JNA, and has recently spent time on a new higher-performance version of it called JFFI. Wayne also became a JRuby committer this spring, and perhaps his most impressive contribution to date is a full FFI library for JRuby, based on JNA (eventually JFFI, once we migrate fully) and implementing the full set of what we and Evan agreed would be "FFI API 1.0". We shipped the completed FFI support in JRuby 1.1.4. | |||
The "Passwd" and "Group" structures for functions like 'getpwuid': | |||
<pre> | |||
module Etc | |||
class Passwd < FFI::Struct | |||
layout :pw_name, :string, 0, | |||
:pw_passwd, :string, 4, | |||
:pw_uid, :uint, 8, | |||
:pw_gid, :uint, 12, | |||
:pw_dir, :string, 20, | |||
:pw_shell, :string, 24 | |||
end | |||
class Group < FFI::Struct | |||
layout :gr_name, :string, 0, | |||
:gr_gid, :uint, 8 | |||
end | |||
end | |||
</pre> | |||
In JRuby 1.1.5, we've taken another step forward with the API, adding support for callbacks. How would we represent a callback you pass into a C function from Ruby? | |||
Binding and calling "qsort" with an array of integers: | |||
<pre> | |||
require 'ffi' | |||
module LibC | |||
extend FFI::Library | |||
callback :qsort_cmp, [ :pointer, :pointer ], :int | |||
attach_function :qsort, [ :pointer, :int, :int, :qsort_cmp ], :int | |||
end | |||
p = MemoryPointer.new(:int, 2) | |||
p.put_array_of_int32(0, [ 2, 1 ]) | |||
puts "Before qsort #{p.get_array_of_int32(0, 2).join(', ')}" | |||
LibC.qsort(p, 2, 4) do |p1, p2| | |||
i1 = p1.get_int32(0) | |||
i2 = p2.get_int32(0) | |||
i1 < i2 ? -1 : i1 > i2 ? 1 : 0 | |||
end | |||
puts "After qsort #{p.get_array_of_int32(0, 2).join(', ')}" | |||
</pre> | |||
What good is having such a library if it doesn't run everywhere? Up until recently, only Rubinius and JRuby supported FFI, which made our case for cross-implementation use pretty weak. Even though we were getting good use out of FFI, there was no motivation for anyone to use it in general, since the standard Ruby implementation had no support. | |||
That is, until Wayne pulled another rabbit out of his hat and implemented FFI for C Ruby as well. The JRuby team is proud to announce a wholly non-JRuby library: FFI is now available on Ruby 1.9 and Ruby 1.8.6/7, in addition to JRuby 1.1.4+ and Rubinius (though Rubinius does not yet support callbacks). | |||
Session showing installation and use of FFI in C Ruby: | |||
<pre> | |||
$ sudo gem install ffi | |||
Password: | |||
Building native extensions. This could take a while... | |||
Successfully installed ffi-0.1.1 | |||
1 gem installed | |||
Installing ri documentation for ffi-0.1.1... | |||
Installing RDoc documentation for ffi-0.1.1... | |||
[headius @ cnutter:~] | |||
$ irb | |||
>> require 'ffi' | |||
=> true | |||
>> module RubyFFI | |||
>> extend FFI::Library | |||
>> attach_function :getuid, [], :uint | |||
>> end | |||
=> #<FFI::Invoker:0x1fe8c> | |||
>> puts RubyFFI.getuid | |||
501 | |||
=> nil | |||
>> | |||
</pre> | |||
Our hope with JRuby's support of FFI and our release of FFI for C Ruby is that we may finally escape the hell of C extensions. | |||
A key feature that's not well documented is the use of FFI's templating system to generate bindings based on the current platform's header files. Here's a sample from the "Etc" module above. | |||
Etc module template, showing how to pull in header files and inspect a struct definition: | |||
<pre> | |||
module Etc | |||
class Passwd < FFI::Struct | |||
@@@ | |||
struct do |s| | |||
s.include "sys/types.h" | |||
s.include "pwd.h" | |||
s.name "struct passwd" | |||
s.field :pw_name, :string | |||
s.field :pw_passwd, :string | |||
s.field :pw_uid, :uint | |||
s.field :pw_gid, :uint | |||
s.field :pw_dir, :string | |||
s.field :pw_shell, :string | |||
end | |||
@@@ | |||
end | |||
class Group < FFI::Struct | |||
@@@ | |||
struct do |s| | |||
s.include "sys/types.h" | |||
s.include "grp.h" | |||
s.name "struct group" | |||
s.field :gr_name, :string | |||
s.field :gr_gid, :uint | |||
end | |||
@@@ | |||
end | |||
end | |||
</pre> | |||
===Docs on FFI=== | |||
[http://wiki.jruby.org/wiki/Calling_C_from_JRuby Calling C from JRuby]<br/> | |||
[http://blog.segment7.net/articles/2008/01/15/rubinius-foreign-function-interfaceRubinius's Foreign Function Interface]<br/> | |||
[http://pluskid.lifegoo.com/?p=370On the Rubinius FFI]<br/> | |||
==Who uses it?== | ==Who uses it?== | ||
The libffi library is useful to anyone trying to build a bridge between interpreted and natively compiled code. Some notable users include: | The libffi library is useful to anyone trying to build a bridge between interpreted and natively compiled code. Some notable users include: | ||
CPython - the default, most-widely used implementation of the Python programming language uses libffi in the standard ctypes library. | *CPython - the default, most-widely used implementation of the Python programming language uses libffi in the standard ctypes library. | ||
OpenJDK - the open-source implementation of the Java Platform Standard Edition uses libffi to bridge between the interpreter and native code for some platforms. | *OpenJDK - the open-source implementation of the Java Platform Standard Edition uses libffi to bridge between the interpreter and native code for some platforms. | ||
js-ctypes - a foreign function interface for javascript that Mozilla will be shipping in Firefox 3.6. | *js-ctypes - a foreign function interface for javascript that Mozilla will be shipping in Firefox 3.6. | ||
Dalvik - Dalvik is the virtual machine which runs the Java platform on Android mobile devices. libffi is used on Android ports for which no custom bridging code has been written. | *Dalvik - Dalvik is the virtual machine which runs the Java platform on Android mobile devices. libffi is used on Android ports for which no custom bridging code has been written. | ||
Java Native Access (JNA) - the JNI-free way to call native code from Java. | *Java Native Access (JNA) - the JNI-free way to call native code from Java. | ||
Ruby-FFI - a Foreign Function Interface extension for Ruby. | *Ruby-FFI - a Foreign Function Interface extension for Ruby. | ||
fsbv - Foreign Structure By Value is a foreign function interface library for Common Lisp that extends the standard CFFI package to include support for passing structure arguments by value. | *fsbv - Foreign Structure By Value is a foreign function interface library for Common Lisp that extends the standard CFFI package to include support for passing structure arguments by value. | ||
JSCocoa - call Objective-C code from javascript on Mac OSX and the iPhone (via the libffi-iphone port). | *JSCocoa - call Objective-C code from javascript on Mac OSX and the iPhone (via the libffi-iphone port). | ||
PyObjC - call Objective-C code from Python on Mac OSX. | *PyObjC - call Objective-C code from Python on Mac OSX. | ||
RubyCocoa - call Objective-C code from Ruby on Mac OSX. | *RubyCocoa - call Objective-C code from Ruby on Mac OSX. | ||
PLT Scheme - call C code from this popular Scheme implementation (also used as the implementation platform for Paul Graham's new Lisp, Arc). | *PLT Scheme - call C code from this popular Scheme implementation (also used as the implementation platform for Paul Graham's new Lisp, Arc). | ||
gcj - the runtime library for the GNU Compiler for the Java Programming Language uses libffi to handle calls back and forth between interpreted and natively compiled code. gcj is part of the GCC, the GNU Compiler Collection. | *gcj - the runtime library for the GNU Compiler for the Java Programming Language uses libffi to handle calls back and forth between interpreted and natively compiled code. gcj is part of the GCC, the GNU Compiler Collection. | ||
==Supported Platforms== | ==Supported Platforms== | ||
Libffi has been ported to many different platforms. For specific configuration details and testing status, please refer to the wiki page [http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.13 | Libffi has been ported to many different platforms. For specific configuration details and testing status, please refer to the wiki page [http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.13 here] | ||
==Authors and Credits== | ==Authors and Credits== | ||
libffi was originally written by Anthony Green | libffi was originally written by Anthony Green<ref>http://moxielogic.org/blog</ref> | ||
The developers of the GNU Compiler Collection project have made innumerable valuable contributions. See this ChangeLog files in the source distribution for details. | The developers of the GNU Compiler Collection project have made innumerable valuable contributions. See this ChangeLog files in the source distribution for details. | ||
Line 70: | Line 198: | ||
Major processor architecture ports were contributed by the following developers: | Major processor architecture ports were contributed by the following developers: | ||
aarch64 Marcus Shawcroft, James Greenhalgh | |||
alpha Richard Henderson | |||
arm Raffaele Sena | |||
blackfin Alexandre Keunecke I. de Mendonca | |||
cris Simon Posnjak, Hans-Peter Nilsson | |||
frv Anthony Green | |||
ia64 Hans Boehm | |||
m32r Kazuhiro Inaoka | |||
m68k Andreas Schwab | |||
microblaze Nathan Rossi | |||
mips Anthony Green, Casey Marshall | |||
mips64 David Daney | |||
moxie Anthony Green | |||
pa Randolph Chung, Dave Anglin, Andreas Tobler | |||
powerpc Geoffrey Keating, Andreas Tobler, | |||
David Edelsohn, John Hornkvist | David Edelsohn, John Hornkvist | ||
powerpc64 Jakub Jelinek | |||
s390 Gerhard Tonn, Ulrich Weigand | |||
sh Kaz Kojima | |||
sh64 Kaz Kojima | |||
sparc Anthony Green, Gordon Irlam | |||
tile-gx/tilepro Walter Lee | |||
x86 Anthony Green, Jon Beniston | |||
x86-64 Bo Thorsen | |||
xtensa Chris Zankel | |||
==Adoption== | ==Adoption== | ||
[http://ruby-doc.org/stdlib-2.0/libdoc/fiddle/rdoc/index.html Fiddle] | [http://ruby-doc.org/stdlib-2.0/libdoc/fiddle/rdoc/index.html Fiddle]<br/> | ||
A libffi wrapper in the Ruby Standard Library<br/> | |||
[http://github.com/ffi/ffi Ruby-FFI]<br/> | |||
A Foreign Function Interface extension for Ruby.<br/> | |||
[http://en.wikipedia.org/wiki/RubyCocoa RubyCocoa]<br/> | |||
Call Objective-C code from Ruby on Mac OSX.<br/> | |||
==See Also== | |||
http://en.wikipedia.org/wiki/Libffi | |||
Line 106: | Line 267: | ||
*https://developer.mozilla.org/en/js-ctypes | *https://developer.mozilla.org/en/js-ctypes | ||
*https://developer.mozilla.org/en/js-ctypes/js-ctypes_reference | *https://developer.mozilla.org/en/js-ctypes/js-ctypes_reference | ||
*http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html | |||
*http://www.rubyinside.com/ruby-ffi-library-calling-external-libraries-now-easier-1293.html | |||
*http://sourceware.org/libffi/ |
Latest revision as of 20:42, 18 September 2013
Ruby libraries to load objects of other languages at run time
This is an advanced topic. Libraries are being developed where Ruby gems can load libraries (and even native code) of other languages.A few open-source projects like FFI are currently working on this.
Introduction
Runtime Library
In computer programming, a runtime library is the API used by a compiler to invoke some of the behaviors of a runtime system. The runtime system implements the execution model and other fundamental behaviors of a programming language. The compiler inserts calls to the runtime library into the executable binary. During execution (run time) of that computer program, execution of those calls to the runtime library cause communication between the application and the runtime system. This often includes functions for input and output, or for memory management. The runtime library may implement a portion of the runtime system's behavior, but if one reads the code of the calls available, they typically are thin wrappers that simply package information and send it to the runtime system. However, sometimes the term runtime library is meant to include the code of the runtime system itself, even though much of that code cannot be directly reached via a library call.
For example, some language features that can be performed only (or are more efficient or accurate) at runtime are implemented in the runtime system and may be invoked via the runtime library API, e.g. some logic errors, array bounds checking, dynamic type checking, exception handling and possibly debugging functionality. For this reason, some programming bugs are not discovered until the program is tested in a "live" environment with real data, despite sophisticated compile-time checking and pre-release testing. In this case, the end user may encounter a runtime error message.
The concept of a runtime library should not be confused with an ordinary program library like that created by an application programmer or delivered by a third party, nor with a dynamic library, meaning a program library linked at run time.
libffi
FFI stands for Foreign Function Interface. A foreign function interface is the popular name for the interface that allows code written in one language to call code written in another language. The libffi library really only provides the lowest, machine dependent layer of a fully featured foreign function interface. A layer must exist above libffi that handles type conversions for values passed between the two languages.<ref>http://sourceware.org/libffi/</ref> libffi is a foreign function interface library. It provides a C programming language interface for calling natively compiled functions given information about the target function at run time instead of compile time. It also implements the opposite functionality: libffi can produce a pointer to a function that can accept and decode any combination of arguments defined at run time. libffi is most often used as a bridging technology between compiled and interpreted language implementations. libffi may also be used to implement plug-ins, where the plug-in's function signatures are not known at the time of creating the host application. Notable users include Python, Haskell, Dalvik, F-Script, PyPy, PyObjC, RubyCocoa, JRuby, Rubinius, MacRuby, gcj, GNU Smalltalk, IcedTea, Cycript, Pawn, Squeak, Java Native Access, Racket,<ref>http://en.wikipedia.org/wiki/Libffi#cite_note-2</ref> Embeddable Common Lisp and Mozilla.<ref>http://en.wikipedia.org/wiki/Libffi#cite_note-3</ref> On Mac OS X libffi is commonly used with BridgeSupport, which provides programming language neutral descriptions of framework interfaces, and Nu which binds direct Objective-C access from Lisp. libffi has been widely ported and is released under a MIT license.
How does it work?<ref>http://www.rubyinside.com/ruby-ffi-library-calling-external-libraries-now-easier-1293.html</ref>
"One of the largest problems plaguing Ruby implementations [..] is the ever-painful story of "extensions". In general, these take the form of a dynamic library, usually written in C, that plugs into and calls Ruby's native API as exposed through ruby.h and libruby."
The many compiled bridges between external libraries and Ruby pose a problem for alternate implementations like JRuby, because of the complexity involved in exposing internals of the implementation or expensive serialization in both directions. Instead, an interface is necessary so that instead of developing libraries that act only as unique bridges to others, we can just have one library that provides the interface to any arbitrary library of our choice.
Ruby already has a library called "dl" that makes it possible to dynamically link external libraries with Ruby. It's a bit arcane though, and Charles points out that it's not widely used "because of real or perceived bugs." Given this, and given the need for an implementation that can be compatible with JRuby, Wayne Meissner has developed "FFI", a new Ruby library that provides "Foreign Function Interface" features to Ruby.
A basic demonstration of a Ruby script that uses C's getpid function should be enough to demonstrate the simplicity of FFI:
require 'ffi' module GetPid extend FFI::Library attach_function :getpid, [], :uint end puts GetPid.getpid
Progress of FFI<ref>http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html</ref>
One of the largest problems plaguing Ruby implementations is the ever-painful story of "extensions". In general, these take the form of a dynamic library, usually written in C, that plugs into and calls Ruby's native API as exposed through ruby.h and libruby. Ignoring for the moment the fact that this API exposes way more of Ruby's internals than it should, extensions present a very difficult problem for other implementations:
Do we support them or not?
In many cases, this question is answered for us; most extensions require access to object internals we can't expose, or can't expose without extremely expensive copying back and forth. But there's also a silver lining: the vast majority of C-based extensions exist solely to wrap another library.
Isn't it obvious what's needed here?
This problem has been tackled by a number of libraries on a number of platforms. On the JVM, there's Java Native Access (JNA). On Python, there's ctypes. And even on Ruby, there's the "dl" stdlib, wrapping libdl for programmatic access to dynamic libraries. But dl is not widely used, because of real or perceived bugs and a rather arcane API. Something better is needed.
Wayne is one of the primary maintainers of JNA, and has recently spent time on a new higher-performance version of it called JFFI. Wayne also became a JRuby committer this spring, and perhaps his most impressive contribution to date is a full FFI library for JRuby, based on JNA (eventually JFFI, once we migrate fully) and implementing the full set of what we and Evan agreed would be "FFI API 1.0". We shipped the completed FFI support in JRuby 1.1.4.
The "Passwd" and "Group" structures for functions like 'getpwuid':
module Etc class Passwd < FFI::Struct layout :pw_name, :string, 0, :pw_passwd, :string, 4, :pw_uid, :uint, 8, :pw_gid, :uint, 12, :pw_dir, :string, 20, :pw_shell, :string, 24 end class Group < FFI::Struct layout :gr_name, :string, 0, :gr_gid, :uint, 8 end end
In JRuby 1.1.5, we've taken another step forward with the API, adding support for callbacks. How would we represent a callback you pass into a C function from Ruby?
Binding and calling "qsort" with an array of integers:
require 'ffi' module LibC extend FFI::Library callback :qsort_cmp, [ :pointer, :pointer ], :int attach_function :qsort, [ :pointer, :int, :int, :qsort_cmp ], :int end p = MemoryPointer.new(:int, 2) p.put_array_of_int32(0, [ 2, 1 ]) puts "Before qsort #{p.get_array_of_int32(0, 2).join(', ')}" LibC.qsort(p, 2, 4) do |p1, p2| i1 = p1.get_int32(0) i2 = p2.get_int32(0) i1 < i2 ? -1 : i1 > i2 ? 1 : 0 end puts "After qsort #{p.get_array_of_int32(0, 2).join(', ')}"
What good is having such a library if it doesn't run everywhere? Up until recently, only Rubinius and JRuby supported FFI, which made our case for cross-implementation use pretty weak. Even though we were getting good use out of FFI, there was no motivation for anyone to use it in general, since the standard Ruby implementation had no support.
That is, until Wayne pulled another rabbit out of his hat and implemented FFI for C Ruby as well. The JRuby team is proud to announce a wholly non-JRuby library: FFI is now available on Ruby 1.9 and Ruby 1.8.6/7, in addition to JRuby 1.1.4+ and Rubinius (though Rubinius does not yet support callbacks).
Session showing installation and use of FFI in C Ruby:
$ sudo gem install ffi Password: Building native extensions. This could take a while... Successfully installed ffi-0.1.1 1 gem installed Installing ri documentation for ffi-0.1.1... Installing RDoc documentation for ffi-0.1.1... [headius @ cnutter:~] $ irb >> require 'ffi' => true >> module RubyFFI >> extend FFI::Library >> attach_function :getuid, [], :uint >> end => #<FFI::Invoker:0x1fe8c> >> puts RubyFFI.getuid 501 => nil >>
Our hope with JRuby's support of FFI and our release of FFI for C Ruby is that we may finally escape the hell of C extensions.
A key feature that's not well documented is the use of FFI's templating system to generate bindings based on the current platform's header files. Here's a sample from the "Etc" module above.
Etc module template, showing how to pull in header files and inspect a struct definition:
module Etc class Passwd < FFI::Struct @@@ struct do |s| s.include "sys/types.h" s.include "pwd.h" s.name "struct passwd" s.field :pw_name, :string s.field :pw_passwd, :string s.field :pw_uid, :uint s.field :pw_gid, :uint s.field :pw_dir, :string s.field :pw_shell, :string end @@@ end class Group < FFI::Struct @@@ struct do |s| s.include "sys/types.h" s.include "grp.h" s.name "struct group" s.field :gr_name, :string s.field :gr_gid, :uint end @@@ end end
Docs on FFI
Calling C from JRuby
Foreign Function Interface
the Rubinius FFI
Who uses it?
The libffi library is useful to anyone trying to build a bridge between interpreted and natively compiled code. Some notable users include:
- CPython - the default, most-widely used implementation of the Python programming language uses libffi in the standard ctypes library.
- OpenJDK - the open-source implementation of the Java Platform Standard Edition uses libffi to bridge between the interpreter and native code for some platforms.
- js-ctypes - a foreign function interface for javascript that Mozilla will be shipping in Firefox 3.6.
- Dalvik - Dalvik is the virtual machine which runs the Java platform on Android mobile devices. libffi is used on Android ports for which no custom bridging code has been written.
- Java Native Access (JNA) - the JNI-free way to call native code from Java.
- Ruby-FFI - a Foreign Function Interface extension for Ruby.
- fsbv - Foreign Structure By Value is a foreign function interface library for Common Lisp that extends the standard CFFI package to include support for passing structure arguments by value.
- JSCocoa - call Objective-C code from javascript on Mac OSX and the iPhone (via the libffi-iphone port).
- PyObjC - call Objective-C code from Python on Mac OSX.
- RubyCocoa - call Objective-C code from Ruby on Mac OSX.
- PLT Scheme - call C code from this popular Scheme implementation (also used as the implementation platform for Paul Graham's new Lisp, Arc).
- gcj - the runtime library for the GNU Compiler for the Java Programming Language uses libffi to handle calls back and forth between interpreted and natively compiled code. gcj is part of the GCC, the GNU Compiler Collection.
Supported Platforms
Libffi has been ported to many different platforms. For specific configuration details and testing status, please refer to the wiki page here
Authors and Credits
libffi was originally written by Anthony Green<ref>http://moxielogic.org/blog</ref> The developers of the GNU Compiler Collection project have made innumerable valuable contributions. See this ChangeLog files in the source distribution for details.
Some of the ideas behind libffi were inspired by Gianni Mariani's free gencall library for Silicon Graphics machines.
The closure mechanism was designed and implemented by Kresten Krab Thorup.
Major processor architecture ports were contributed by the following developers:
aarch64 Marcus Shawcroft, James Greenhalgh
alpha Richard Henderson
arm Raffaele Sena
blackfin Alexandre Keunecke I. de Mendonca
cris Simon Posnjak, Hans-Peter Nilsson
frv Anthony Green
ia64 Hans Boehm
m32r Kazuhiro Inaoka
m68k Andreas Schwab
microblaze Nathan Rossi
mips Anthony Green, Casey Marshall
mips64 David Daney
moxie Anthony Green
pa Randolph Chung, Dave Anglin, Andreas Tobler
powerpc Geoffrey Keating, Andreas Tobler, David Edelsohn, John Hornkvist
powerpc64 Jakub Jelinek
s390 Gerhard Tonn, Ulrich Weigand
sh Kaz Kojima
sh64 Kaz Kojima
sparc Anthony Green, Gordon Irlam
tile-gx/tilepro Walter Lee
x86 Anthony Green, Jon Beniston
x86-64 Bo Thorsen
xtensa Chris Zankel
Adoption
Fiddle
A libffi wrapper in the Ruby Standard Library
Ruby-FFI
A Foreign Function Interface extension for Ruby.
RubyCocoa
Call Objective-C code from Ruby on Mac OSX.
See Also
http://en.wikipedia.org/wiki/Libffi
References
- http://github.com/atgreen/libffi/blob/master/LICENSE
- http://repository.readscheme.org/ftp/papers/sw2004/barzilay.pdf
- http://hg.mozilla.org/mozilla-central/file/2dc00d4b379a/js/ctypes/libffi
- https://developer.mozilla.org/en/js-ctypes
- https://developer.mozilla.org/en/js-ctypes/js-ctypes_reference
- http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html
- http://www.rubyinside.com/ruby-ffi-library-calling-external-libraries-now-easier-1293.html
- http://sourceware.org/libffi/