GithubHelp home page GithubHelp logo

ffi-compiler's Introduction

ffi-compiler is a ruby library for automating compilation of native libraries for use with ffi

To use, define your own ruby->native API using ffi, implement it in C, then use ffi-compiler to compile it.

Example

Directory layout
lib
  |- example
      |- example.rb
      
ext
  |- example.c
  |- Rakefile
  
example.gemspec
lib/example/example.rb
require 'ffi'
require 'ffi-compiler/loader'

module Example
  extend FFI::Library
  ffi_lib FFI::Compiler::Loader.find('example')
  
  # example function which takes no parameters and returns long
  attach_function :example, [], :long
end
ext/example.c
long
example(void)
{
    return 0xdeadbeef;
}
ext/Rakefile
require 'ffi-compiler/compile_task'

FFI::Compiler::CompileTask.new('example') do |c|
  c.have_header?('stdio.h', '/usr/local/include')
  c.have_func?('puts')
  c.have_library?('z')
end
example.gemspec
Gem::Specification.new do |s|
  s.extensions << 'ext/Rakefile'
  s.name = 'example'
  s.version = '0.0.1'
  s.email = 'ffi-example'
  s.files = %w(example.gemspec) + Dir.glob("{lib,spec,ext}/**/*")
  s.add_dependency 'rake'
  s.add_dependency 'ffi-compiler'
end
Build gem and install it
gem build example.gemspec && gem install example-0.0.1.gem
Successfully built RubyGem
  Name: example
  Version: 0.0.1
  File: example-0.0.1.gem
Building native extensions.  This could take a while...
Successfully installed example-0.0.1
Test it
$ irb
2.0.0dev :001 > require 'example/example'
 => true 
2.0.0dev :002 > puts "Example.example=#{Example.example.to_s(16)}"
Example.example=deadbeef
 => nil 

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  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ffi-compiler's Issues

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

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.

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)

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?

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

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

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.