According to the official ruby About page it's easier to extend Ruby with C than Perl. I'm not a (perl) XS guy, but I find it dirt simple to write something quick and simple with Inline::C, so why is it easier in Ruby?
Writing C extensions in Ruby is easier than in Perl or Python, with a very elegant API for calling Ruby from C. This includes calls for embedding Ruby in software, for use as a scripting language. A SWIG interface is also available.
Any further explanation from those that do more C extensions would be useful.
(Full disclosure, I am a Perl programmer)
The Ruby C API certainly looks much nicer than Perl's. It looks like a regular C library with functions that correspond to Ruby code. Perl's API is a mess of macros within macros within macros and magic threading flags. Using the Perl API outside of the Perl core is certainly a secondary concern. Ruby definitely wins on not being bowel clenchingly terrifying.
While Ruby has a better C API, Perl has the better tutorials on how to do anything with it. The generated Ruby documentation lacks any sort of cohesive tutorial or often any descriptive text at all. It's possible I'm looking in the wrong place but that's all that was offered. In contrast, the Perl API documentation is hand written prose with useful information about what each function does. In addition, there's over a dozen documents in the core docs about using Perl and C. I'd say Perl wins on docs.
FFI looks quite impressive. The closest thing Perl has to FFI is Inline::C which is a wrapper around the mess of XS. It's primary use is to inline C code into your Perl program, but you can also use it to access C library functions.
Here's a trivial example similar to nash's getpid example.
use Inline
C => Config =>
ENABLE => "AUTOWRAP";
use Inline C => q{ int getpid(); };
print getpid();
Now, I am cheating because technically getpid returns pid_t on my system, but that's just an integer. FFI seems to have an awful lot of special cased code for getpid, so I suspect it's ease of use will correspond directly to whether FFI has already taken care of it. Trivial examples are trivial. It would be interesting to see what happens when typical complications arise, such as functions that return pre-allocated memory and have odd types and throw around structs.
While FFI and Inline::C can be used to do the same thing, how they do it looks very, very different. Inline::C is actually compiling and caching C code. FFI is somehow not doing any compiling. I'm not sure if that's really for real, or if the compilation is done for you at install time for common libraries.
In addition, FFI smooths the portability problems across the various Ruby implementations and their different ways of calling native APIs. This is something Inline::C doesn't have to do, and quite frankly it's amazing if it really works. One benefit is the FFI interface is much smoother than Inline::C. With Inline::C, it's very clear that you're writing a wrapper around a C compiler.
With FFI it's very easy to extend Ruby with C. This is an example from github
require 'rubygems'
require 'ffi'
module Foo
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function :getpid, [ ], :int
end
puts "My pid=#{Foo.getpid}"
You don’t need a compiler installed on your system to be able to run FFI extensions. On linux, you also do not need to install the development versions of libraries, just the runtime versions. Of course, the libraries you link against will need to have been compiled at some point, but odds are you won’t have had to do it.
https://github.com/ffi/ffi/wiki/why-use-ffi
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With