https://github.com/madeindjs/cruby
https://github.com/madeindjs/cruby
Last synced: about 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/madeindjs/cruby
- Owner: madeindjs
- License: mit
- Archived: true
- Created: 2019-01-10T16:31:07.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2019-01-11T15:18:19.000Z (over 7 years ago)
- Last Synced: 2025-02-05T21:41:51.791Z (over 1 year ago)
- Language: Ruby
- Size: 23.4 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.adoc
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
= Cruby
:source-highlighter: rouge
Tests pour mélanger du code Ruby et du C.
== Création de la librairie
Nous allons générer une nouvelle gemme appelé `cruby` (oui je sais, c'est un moche..). Pour cela, on utilise https://bundler.io/[Bundler].
[source, console]
----
$ bundle gem cruby
----
Afin que notre librairie soir valide, il faut lui ajouter des informations dans le fichier `cruby.gemspec`:
[source,ruby]
.cruby.gemspec
----
# ...
Gem::Specification.new do |spec|
# ...
spec.summary = %q{Somes tests with Ruby and C}
spec.description = %q{Somes tests with Ruby and C}
spec.homepage = "https://github.com/madeindjs/cruby"
spec.license = "MIT"
# ...
if spec.respond_to?(:metadata)
spec.metadata["allowed_push_host"] = "https://rubygems.org"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "https://github.com/madeindjs/cruby"
spec.metadata["changelog_uri"] = "https://github.com/madeindjs/cruby"
else
# ...
end
# ...
end
----
Maintenant nous pouvons _commiter_:
[source, console]
----
$ git commit -am "Init project"
----
== Premier test
Dans ce premier test nous allons essayer d'ajouter une méthode à notre classe `Cruby`.
La première chose à savoir est que tous le code non-Ruby doit se situer dans le dossier `ext` footnote:[Ce dossier n'est d’ailleurs pas généré par Ruby]. Ce dossier se composera de sous-dossiers qui sont en quelques sorte des modules.
[source, bash]
----
$ mkdir -p ext/cruby
$ touch ext/cruby/extconf.rb
$ touch ext/cruby/Init_crubyc.c
----
Dedans nous allons créer deux fichiers. Le premier `ext/cruby/extconf.rb` contient des instructions pour compiler notre module
[source, ruby]
.ext/cruby/extconf.rb
----
require 'mkmf'
create_makefile 'crubyc'
----
NOTE: Le fichier `extconf.rb` permet d'effectuer quelques vérifications avant la compilation. `mkmf` donne accès à plusieurs fonctions comme `have_header` pour vérifier si la librairie est disponible pour la compilation ou encore `find_executable` pour vérifier si l’exécutable est présent.
Le deuxième `ext/cruby/Init_crubyc.c` contient notre code externe
[source, c]
.ext/cruby/Init_crubyc.c
----
#include
VALUE rb_cprint(VALUE self, VALUE str) {
if (RB_TYPE_P(str, T_STRING) == 1) {
return rb_sprintf("Printed from C code: %ld", str);
}
return Qnil;
}
void Init_crubyc() {
VALUE mod = rb_define_module("Cruby");
rb_define_singleton_method(mod, "cprint", rb_cprint, 1);
}
----
Dans le code externe, nous avons simplement récupéré le module `Cruby` et nous lui avons ajouté une méthode `cprint`.
Écrivons un test unitaire pour tester notre méthode:
[source, c]
.spec/cruby_spec.rb
----
RSpec.describe Cruby do
it 'Should do something with no error' do
expect(Cruby.cprint('hello')).to match(/Printed from C/)
end
end
----
Nous allons maintenant utiliser la librairie https://github.com/luislavena/rake-compiler[rake-compiler] pour compiler notre code C footnote:[Il est possible de le faire à la main mais je ne vais pas en parler. S'il existe une librairie nous facilitant la tâche, autant l'utiliser]. Ajoutons donc la gemme.
[source, bash]
----
$ bundle add rake-compiler
----
Afin de l'utiliser, nous allons créer une tâche qui va compiler le code et lancer les tests unitaires. C'est à dire une tâche qui va successivement appeler la tâche `compile` et `spec`.
[source, ruby]
.Rakefile
----
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
require 'rake/extensiontask'
# Import rspec task
RSpec::Core::RakeTask.new(:spec)
task default: :spec
# create `compile:crubyc` task
Rake::ExtensionTask.new('crubyc')
desc 'Compile extensions and run tests'
task test: %i[compile spec] do
end
----
Et maintenant, l'instant de vérité, on lance les tests:
[source, console]
----
$ rake test
Cruby
Should do something with no error
Finished in 0.00397 seconds (files took 0.2523 seconds to load)
1 example, 0 failures
----
== Liens
- http://chris911.github.io/blog/2014/08/10/writing-a-ruby-gem-with-c-extension/
- http://aaronbedra.com/extending-ruby/
- https://github.com/ruby/ruby/blob/trunk/doc/extension.rdoc