Code Monkey home page Code Monkey logo

ffi-compiler's Introduction

Description

Ruby-FFI is a gem for programmatically loading dynamically-linked native libraries, binding functions within them, and calling those functions from Ruby code. Moreover, a Ruby-FFI extension works without changes on CRuby (MRI), JRuby, Rubinius and TruffleRuby. Discover why you should write your next extension using Ruby-FFI.

Features

  • Intuitive DSL
  • Supports all C native types
  • C structs (also nested), enums and global variables
  • Callbacks from C to Ruby
  • Automatic garbage collection of native memory
  • Usable in Ractor: How-to-use-FFI-in-Ruby-Ractors

Synopsis

require 'ffi'

module MyLib
  extend FFI::Library
  ffi_lib 'c'
  attach_function :puts, [ :string ], :int
end

MyLib.puts 'Hello, World using libc!'

For less minimalistic and more examples you may look at:

Requirements

When installing the gem on CRuby (MRI), you will need:

  • A C compiler (e.g., Xcode on macOS, gcc or clang on everything else) Optionally (speeds up installation):
  • The libffi library and development headers - this is commonly in the libffi-dev or libffi-devel packages

The ffi gem comes with a builtin libffi version, which is used, when the system libffi library is not available or too old. Use of the system libffi can be enforced by:

gem install ffi -- --enable-system-libffi        # to install the gem manually
bundle config build.ffi --enable-system-libffi   # for bundle install

or prevented by --disable-system-libffi.

On Linux systems running with PaX (Gentoo, Alpine, etc.), FFI may trigger mprotect errors. You may need to disable mprotect for ruby (paxctl -m [/path/to/ruby]) for the time being until a solution is found.

On FreeBSD systems pkgconf must be installed for the gem to be able to compile using clang. Install either via packages pkg install pkgconf or from ports via devel/pkgconf.

On JRuby and TruffleRuby, there are no requirements to install the FFI gem, and require 'ffi' works even without installing the gem (i.e., the gem is preinstalled on these implementations).

Installation

From rubygems:

[sudo] gem install ffi

From a Gemfile using git or GitHub

gem 'ffi', github: 'ffi/ffi', submodules: true

or from the git repository on github:

git clone git://github.com/ffi/ffi.git
cd ffi
git submodule update --init --recursive
bundle install
rake install

Install options:

  • --enable-system-libffi : Force usage of system libffi
  • --disable-system-libffi : Force usage of builtin libffi
  • --enable-libffi-alloc : Force closure allocation by libffi
  • --disable-libffi-alloc : Force closure allocation by builtin method

License

The ffi library is covered by the BSD license, also see the LICENSE file. The specs are covered by the same license as ruby/spec, the MIT license.

Credits

The following people have submitted code, bug reports, or otherwise contributed to the success of this project:

ffi-compiler's People

Contributors

alexeymorozov avatar davispuh avatar enebo avatar frahugo avatar le0pard avatar luislavena avatar matoro avatar vp-of-awesome avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ffi-compiler's Issues

Cannot build 2 extensions

I need to build to separate libraries. In the gemspec, I can provide an array of extensions, as per the documentation:

  spec.extensions    = [
    'ext/mygem/lib1/Rakefile',
    'ext/mygem/lib2/Rakefile'
  ]

Lib1 gets compiled, but nothing is ran for lib2. If I swap them, lib2 gets compiled but not lib1.

Would that be a bug in rubygems? Or does the rake task has to return or do something special?

How to create stub lib to call methods from C++ dynamic library?

May be dumb question, as I haven't work with C since university, but I can't figure it out.

In ffi/ffi#281 it's advised to use ffi-compiler to create a stub lib and binding that using FFI.

So, I have some custom.h file somewhere in my system (probably installed from some libcustom-dev package) and I have libcustom.so somewhere in my system (probably installed from some libcustom package).

In that custom.h contained next declaration:

int scaleImg( unsigned char *BufImg, int &Maxx, int &Maxy, int Dpi );

In corresponding libcustom.so it contained with C++ mangled name:

$ nm -gU libcustom.so | grep scaleImg
0000000000046410 T __Z8scaleImgPhRiS0_i

Question: how to use ffi-compiler in such a case to be able to call scaleImg from libcustom.so?

Will it be enough to do something like this in, say, example.cpp:

#include "example.h"
#include <custom.h>

RBFFI_EXPORT int rbScaleImg( unsigned char *BufImg, int &Maxx, int &Maxy, int Dpi );
{
  return scaleImg( BufImg, Maxx, Maxy, Dpi );
}

Thank you in advance.

Related issue: ffi/ffi#554

Compilation error if C files are found in a sub-folder

Let's say I have the following directory structure:

example/
├── Rakefile
├── example-0.0.1.gem
├── example.gemspec
├── ext
│   ├── Rakefile
│   ├── example.c
│   └── utils
│       └── utils.c
└── lib
    └── example
        └── example.rb

When installing the gem, I get the following error:

Don't know how to build task 'x86_64-darwin/utils'

Tasks: TOP => default => x86_64-darwin/libexample.bundle => x86_64-darwin/utils/utils.o
(See full trace by running task with --trace)

Problem with function visibility on Linux

I have issue with https://github.com/le0pard/webp-ffi. Writting library by using ffi and ffi-compiler. Check my library by rspec.

My Rackfile:

require 'bundler/setup'
require 'rake'
require 'rake/clean'
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
require 'ffi-compiler/compile_task'

desc "compiler tasks"
namespace "ffi-compiler" do
  FFI::Compiler::CompileTask.new('ext/webp_ffi/webp_ffi') do |c|
    c.have_header?('stdio.h', '/usr/local/include')
    c.have_func?('puts')
    c.have_library?('z')
    c.have_header?('decode.h', '/usr/local/include')
    c.have_header?('encode.h', '/usr/local/include')
    c.have_func?('WebPDecoderConfig')
    c.have_func?('WebPGetInfo')
    c.have_library?('webp')
    c.cflags << "-arch x86_64" if c.platform.mac?
    c.ldflags << "-arch x86_64" if c.platform.mac?
  end
end
task :compile => ["ffi-compiler:default"]

desc "run specs"
task :spec do
  RSpec::Core::RakeTask.new
end

task :default => [:clean, :compile, :spec]

CLEAN.include('ext/**/*{.o,.log,.so,.bundle}')
CLEAN.include('lib/**/*{.o,.log,.so,.bundle}')
CLEAN.include('ext/**/Makefile')

Running on Mac OS:

$ rake                                                                                                                                                                                                      ruby-2.0.0-p0 master 1c3740c ✗
rm -r ext/webp_ffi/x86_64-darwin/util.o
rm -r ext/webp_ffi/x86_64-darwin/webp_ffi.o
rm -r ext/webp_ffi/x86_64-darwin/libwebp_ffi.bundle
rm -r ext/webp_ffi/x86_64-darwin/libwebp_ffi.bundle
rm -r ext/webp_ffi/x86_64-darwin/util.o
rm -r ext/webp_ffi/x86_64-darwin/webp_ffi.o
gcc-4.2 -fexceptions -O -fno-omit-frame-pointer -fno-strict-aliasing -arch x86_64 -DHAVE_PUTS=1 -DHAVE_STDIO_H=1 -o ext/webp_ffi/x86_64-darwin/util.o -c ext/webp_ffi/util.c
gcc-4.2 -fexceptions -O -fno-omit-frame-pointer -fno-strict-aliasing -arch x86_64 -DHAVE_PUTS=1 -DHAVE_STDIO_H=1 -o ext/webp_ffi/x86_64-darwin/webp_ffi.o -c ext/webp_ffi/webp_ffi.c
gcc-4.2 -bundle -o ext/webp_ffi/x86_64-darwin/libwebp_ffi.bundle ext/webp_ffi/x86_64-darwin/util.o ext/webp_ffi/x86_64-darwin/webp_ffi.o -fexceptions -arch x86_64 -lz -lwebp
/Users/leo/.rvm/rubies/ruby-2.0.0-p0/bin/ruby -S rspec ./spec/webp_ffi_spec.rb

WebpFfi
  calculate plus 100 by test
  #webp_size
    1.webp image size == [400, 301]
    2.webp image size == [386, 395]
    3.webp image size == [300, 300]
    4.webp image size == [2000, 2353]
    nil for non-webp image

Finished in 0.02231 seconds
6 examples, 0 failures

And running on Ubuntu 12.04:

$ rake
rm -r ext/webp_ffi/x86_64-linux/util.o
rm -r ext/webp_ffi/x86_64-linux/webp_ffi.o
rm -r ext/webp_ffi/x86_64-linux/libwebp_ffi.so
rm -r ext/webp_ffi/x86_64-darwin/libwebp_ffi.bundle
rm -r ext/webp_ffi/x86_64-darwin/util.o
rm -r ext/webp_ffi/x86_64-darwin/webp_ffi.o
gcc -fexceptions -O -fno-omit-frame-pointer -fno-strict-aliasing -fPIC -DHAVE_PUTS=1 -DHAVE_STDIO_H=1 -o ext/webp_ffi/x86_64-linux/util.o -c ext/webp_ffi/util.c
gcc -fexceptions -O -fno-omit-frame-pointer -fno-strict-aliasing -fPIC -DHAVE_PUTS=1 -DHAVE_STDIO_H=1 -o ext/webp_ffi/x86_64-linux/webp_ffi.o -c ext/webp_ffi/webp_ffi.c
gcc -shared -o ext/webp_ffi/x86_64-linux/libwebp_ffi.so ext/webp_ffi/x86_64-linux/util.o ext/webp_ffi/x86_64-linux/webp_ffi.o -fexceptions -lz -lwebp
/home/vagrant/.rvm/rubies/ruby-2.0.0-p0/bin/ruby -S rspec ./spec/webp_ffi_spec.rb
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/ffi-1.4.0/lib/ffi/library.rb:251:in `attach_function': Function 'WebPGetInfo' not found in [/vagrant/ext/webp_ffi/x86_64-linux/libwebp_ffi.so] (FFI::NotFoundError)
    from /vagrant/lib/webp_ffi/c.rb:3:in `<module:C>'
    from /vagrant/lib/webp_ffi/c.rb:2:in `<module:WebpFfi>'
    from /vagrant/lib/webp_ffi/c.rb:1:in `<top (required)>'
    from /vagrant/lib/webp_ffi.rb:11:in `require'
    from /vagrant/lib/webp_ffi.rb:11:in `<top (required)>'
    from /vagrant/spec/spec_helper.rb:3:in `require'
    from /vagrant/spec/spec_helper.rb:3:in `<top (required)>'
    from /vagrant/spec/webp_ffi_spec.rb:1:in `require'
    from /vagrant/spec/webp_ffi_spec.rb:1:in `<top (required)>'
    from /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/configuration.rb:819:in `load'
    from /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/configuration.rb:819:in `block in load_spec_files'
    from /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/configuration.rb:819:in `each'
    from /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/configuration.rb:819:in `load_spec_files'
    from /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/command_line.rb:22:in `run'
    from /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/runner.rb:80:in `run'
    from /home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/runner.rb:17:in `block in autorun'
rake aborted!
/home/vagrant/.rvm/rubies/ruby-2.0.0-p0/bin/ruby -S rspec ./spec/webp_ffi_spec.rb failed
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/rake_task.rb:156:in `run_task'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/rake_task.rb:124:in `block (2 levels) in initialize'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.13.0/lib/rspec/core/rake_task.rb:122:in `block in initialize'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/bin/ruby_noexec_wrapper:14:in `eval'
/home/vagrant/.rvm/gems/ruby-2.0.0-p0/bin/ruby_noexec_wrapper:14:in `<main>'
Tasks: TOP => default => spec
(See full trace by running task with --trace)

What my configuration is invalid? I coudn't find problem. Thanks in advance.

P.S. If you want test my lib you should install Web-P lib https://developers.google.com/speed/webp/docs/compiling

1.2.0 seems to break some packages with arg splitting

We had a report in Gentoo at https://bugs.gentoo.org/906892 of http-parser-1.2.3 failing to build with ffi-compiler-1.2.0 like so:

mkdir -p x86_64-linux/http-parser
x86_64-pc-linux-gnu-gcc -O2 -pipe -march\=native -fno-diagnostics-color -Wall\ -Wextra\ -O3 -fPIC -o x86_64-linux/http-parser/http_parser.o -c ./http-parser/http_parser.c
x86_64-pc-linux-gnu-gcc: error: unrecognized command-line option -Wall -Wextra -O3
rake aborted!
Command failed with status (1): [x86_64-pc-linux-gnu-gcc -O2 -pipe -march\=...]

@matoro points out that the args from https://github.com/cotag/http-parser/blob/master/ext/Rakefile#L4 (the package itself) seem to not be split by ffi-compiler.

See also #22.

Cannot install with bundler or with gem -P

I'm trying to install another gem (https://github.com/abonas/kubeclient), which has a dependency on ffi-compiler. However, bundler says:

The gem ffi-compiler-1.0.1 can't be installed because the security policy didn't allow it, with the message: no digests provided (probable bug)

Actually, if I try install it with gem install -P (trust policy) it also fails:

$ gem install ffi-compiler -P MediumSecurity
Fetching ffi-compiler-1.0.1.gem
ERROR:  While executing gem ... (Gem::Security::Exception)
    no digests provided (probable bug)

and even with NoSecurity

$ gem install ffi-compiler -P NoSecurity 
WARNING:  email:steve (at) advancedcontrol.com.au is not trusted for ffi-compiler-1.0.1
ERROR:  While executing gem ... (Gem::Security::Exception)
    missing digest for metadata.gz

Probably ffi-compiler gem should be re-uploaded with a fresh certificate / digest.

Bundler version 2.2.15
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin20]
gem 3.2.15

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.