RubyGems: Gemas con extensiones (6)

Muchas gemas usan extensiones para envolver bibliotecas que están escritas en C con un envoltorio de Ruby.

Los ejemplos incluyen nokogiri que envuelve libxml2 y libxslt, pg que es una interfaz para la base de datos PostgreSQL y las gemas mysql y mysql2 que proporcionan una interfaz para la base de datos MySQL.

Crear una gema que use una extensión implica varios pasos.

Esta guía se centra en lo que debes poner en la especificación de tu gema para que sea lo más fácil de mantener posible.

La extensión en esta guía envolverá malloc() y free() de la biblioteca estándar de C.

Diseño de GEMAS

Cada gema debe comenzar con un Rakefile que contiene las tareas que necesitan los desarrolladores para trabajar en la gema.

Los archivos de la extensión deben ir en el directorio ext/ en un directorio que coincida con el nombre de la extensión.

Para este ejemplo, usaremos “my_malloc” para el nombre.

Algunas extensiones se escribirán parcialmente en C y parcialmente en ruby. Si vas a admitir varios idiomas, como extensiones C y Java, debes colocar los archivos ruby específicos de C en el directorio ext/ y también en el directorio lib/.

Rakefile
ext/my_malloc/extconf.rb               # extension configuration
ext/my_malloc/my_malloc.c              # extension source
lib/my_malloc.rb                       # generic features

Cuando se construya la extensión, los archivos ext/my_malloc/lib/ se instalarán en el directorio lib/ por ti.

Extconf.rb

El extconf.rb configura un Makefile que se encarga de construir tu extensión.

El extconf.rb debe verificar las funciones, macros y bibliotecas compartidas necesarias de las que depende la extensión.

El extconf.rb debe salir con un error si falta alguno de estos.

Aquí hay un extconf.rb que busca malloc() y free() creando un Makefile que instalará la extensión construida en lib/my_malloc/my_malloc.so:

require "mkmf"

abort "missing malloc()" unless have_func "malloc"
abort "missing free()"   unless have_func "free"

create_makefile "my_malloc/my_malloc"

Consulte la documentación de mkmf y de la extension.rdoc para obtener más información sobre cómo crear un extconf.rb y para obtener documentación sobre estos métodos.

Extensión C

La extensión C que envuelve malloc() y free() entra ext/my_malloc/my_malloc.c.

Aquí está el listado:

#include <ruby.h>

struct my_malloc {
  size_t size;
  void *ptr;
};

static void
my_malloc_free(void *p) {
  struct my_malloc *ptr = p;

  if (ptr->size > 0)
    free(ptr->ptr);
}

static VALUE
my_malloc_alloc(VALUE klass) {
  VALUE obj;
  struct my_malloc *ptr;

  obj = Data_Make_Struct(klass, struct my_malloc, NULL, my_malloc_free, ptr);

  ptr->size = 0;
  ptr->ptr  = NULL;

  return obj;
}

static VALUE
my_malloc_init(VALUE self, VALUE size) {
  struct my_malloc *ptr;
  size_t requested = NUM2SIZET(size);

  if (0 == requested)
    rb_raise(rb_eArgError, "unable to allocate 0 bytes");

  Data_Get_Struct(self, struct my_malloc, ptr);

  ptr->ptr = malloc(requested);

  if (NULL == ptr->ptr)
    rb_raise(rb_eNoMemError, "unable to allocate %ld bytes", requested);

  ptr->size = requested;

  return self;
}

static VALUE
my_malloc_release(VALUE self) {
  struct my_malloc *ptr;

  Data_Get_Struct(self, struct my_malloc, ptr);

  if (0 == ptr->size)
    return self;

  ptr->size = 0;
  free(ptr->ptr);

  return self;
}

void
Init_my_malloc(void) {
  VALUE cMyMalloc;

  cMyMalloc = rb_const_get(rb_cObject, rb_intern("MyMalloc"));

  rb_define_alloc_func(cMyMalloc, my_malloc_alloc);
  rb_define_method(cMyMalloc, "initialize", my_malloc_init, 1);
  rb_define_method(cMyMalloc, "free", my_malloc_release, 0);
}

Esta extensión es simple con solo unas pocas partes:

  • struct my_malloc para mantener la memoria asignada.
  • my_malloc_free() para liberar la memoria asignada después de la recolección de basura.
  • my_malloc_alloc() para crear el objeto contenedor de Ruby.
  • my_malloc_init() para asignar memoria de ruby.
  • my_malloc_release() para liberar memoria de ruby.
  • Init_my_malloc() para registrar las funciones en la clase MyMalloc.

Ahora podemos crear la clase real MyMalloc y vincular métodos recién definidos en Ruby ( lib/my_malloc.rb es el lugar correcto para eso) por ejemplo:

class MyMalloc
  VERSION = "1.0"
end

require "my_malloc/my_malloc"

Puede probar la construcción de la extensión de la siguiente manera:

$ cd ext/my_malloc
$ ruby extconf.rb
checking for malloc()... yes
checking for free()... yes
creating Makefile
$ make
compiling my_malloc.c
linking shared-object my_malloc.bundle
$ cd ../..
$ ruby -Ilib:ext -r my_malloc -e "p MyMalloc.new(5).free"
#<MyMalloc:0x007fed838addb0>

Pero esto se volverá tedioso después de un tiempo. ¡Vamos a automatizarlo!

Compilador de Rake

rake-compiler

es un conjunto de tareas de rake para automatizar la creación de extensiones.

rake-compiler se puede usar con extensiones C o Java en el mismo proyecto (nokogiri lo usa de esta manera).

Primero instala la gema:

$ gem install rake-compiler

Agrega rake-compilador al Rakefile:

require "rake/extensiontask"

Rake::ExtensionTask.new "my_malloc" do |ext|
  ext.lib_dir = "lib/my_malloc"
end

Ahora puedes compilar la extensión rake compile y vincular la tarea de compilación con otras tareas (como las pruebas).

El ajuste lib_dir coloca la biblioteca compartida en lib/my_malloc/my_malloc.so (o .bundle o .dll).

Eso permite que el archivo de nivel superior de la gema sea un archivo ruby. Esto permite escribir las partes que mejor se adaptan a Ruby en Ruby.

Por ejemplo:

class MyMalloc

  VERSION = "1.0"

end

require "my_malloc/my_malloc"

La configuración lib_dir también permite crear una gema que contiene extensiones preconstruidas para múltiples versiones de Ruby.

(No se puede usar una extensión para Ruby 1.9.3 con una extensión para Ruby 2.0.0). lib/my_malloc.rb puede elegir la biblioteca compartida correcta para instalar.

Especificación de GEMAS

El paso final para construir la gema es agregar extconf.rb a la lista de extensiones en gemspec:

Gem::Specification.new "my_malloc", "1.0" do |s|
  # [...]

  s.extensions = %w[ext/my_malloc/extconf.rb]
end

¡Ahora ya puedes construir y liberar tu gema!

Nomenclatura de extensiones

Para evitar interacciones no deseadas entre gemas, es una buena idea que cada gema mantenga todos sus archivos en un solo directorio. Aquí están las recomendaciones para una gema con el nombre “:

  1. ext/es el directorio que contiene los archivos fuente y extconf.rb
  2. ext//.ces el archivo fuente principal (puede haber otros)
  3. ext//.ccontiene una función Init_. (El nombre que sigue Init_a la función debe coincidir exactamente con el nombre de la extensión para que se pueda cargar mediante require).
  4. ext//extconf.rbllama create_makefile('/')solo cuando están presentes todas las piezas necesarias para compilar la extensión.
  5. El gemspec establece extensions = ['ext//extconf.rb']e incluye cualquiera de los archivos fuente de extensión necesarios en la fileslista.
  6. lib/.rbcontiene require '/'que carga la extensión C.

Lecturas sobre la creación de extensiones

  • my_malloc contiene el código fuente de esta extensión con algunos comentarios adicionales.
  • extension.rdoc describe con mayor detalle cómo crear extensiones en Ruby
  • MakeMakefile contiene documentación para mkmf.rb, la biblioteca que extconf.rb usa para detectar funciones de biblioteca Ruby y C
  • rake-compiler integra la construcción de extensiones C y Java en su Rakefile de manera fluida.
  • Escribiendo extensiones de C parte 1 y parte 2 ) por Aaron Patterson
  • Las interfaces a las bibliotecas C se pueden escribir usando ruby y fiddle (parte de la biblioteca estándar) o ruby-ffi
  • Extending Ruby es un capítulo del libro Programación de Ruby sobre la creación de extensiones de C. Tenga en cuenta : este contenido es algo más antiguo y algunas API de extensión C han cambiado.

<<

Relacionado

15 Mejores Lenguajes de Programación que Aprender

Una de las habilidades más importantes para aprender en el mundo de hoy en día, es saber programar con un lenguaje de programación. En la actualidad, las computadoras han entrado en casi todas las industrias, desde el piloto automático de un avión hasta el velocímetro digital de una bicicleta pasando por la inclusión del Internet de las cosas en los pequeños electrodomésticos. Casi todo lo que ¡SEGUIR LEYENDO!

Mejores Libros PDF de Programación y Tecnología GRATIS

Los Mejores Libros PDF Gratuitos de Informática. EL sitio perfecto para aprender a programar desde cero para principiantes con las mejores guías gratis. Esta es la mejor lista de libros de programación en PDF en español del mundo. Una completa biblioteca recopilada de cientos y cientos de libros en PDF que no encontrarás en ninguna parte más. Aquí, vas a encontrar libros enfocados hacía programadores. Sobre ¡SEGUIR LEYENDO!

Más de 1.500 Libros PDF en Inglés de Desarrollo Web, Programación, Seguridad, Robótica, Blockchain, Domótica y Mucho Más

La mejor lista de libros sobre lenguajes de programación en inglés de todo Internet. https://ciberninjas.com/zlibrary/ Libros de Python / Libros PHP / Libros Java / Libros Diseño Meta Listas atariarchives.org atariarchives.org pone a disposición en la Web libros, información y software para Atari y otras computadoras clásicas. Bento Bitsavers.org Bookboon: se requiere cookie de TI y programación</. (requiere @email) DZone - Hojas de trucos (gratis) Conceptf1.blogspot.com ¡SEGUIR LEYENDO!

Comparando Python con otros lenguajes de programación populares

Este artículo analiza los numerosos beneficios de Python como uno de los lenguajes de programación más importantes disponibles y por qué deberías considerar usarlo para tu proyecto de software en lugar de otras opciones populares. Python es considerado como uno de los lenguajes de programación más utilizados para aplicaciones sencillas y prácticas. Los especialistas en TI afirman tener al menos una comprensión rudimentaria de Python y ¡SEGUIR LEYENDO!

Crystal: Un nuevo lenguaje de programación que buscar integrar lo mejor de Ruby y C

Crystal, un nuevo lenguaje de programación de sistemas compilados y orientado a objetos que tiene como objetivo combinar la concisión y amabilidad de Ruby con la eficiencia de C. La versión 1.0 de Crystal tiene una sintaxis cercana a la de Ruby y presenta tipos inferidos estáticamente, enlaces C y macros. El lenguaje de Crystal podría atraer a los desarrolladores con experiencia en Ruby/Rails o Elixir/Phoenix. ¡SEGUIR LEYENDO!

Cursos de Udemy con Cupón Gratuito 2019 (en Inglés)(parte 2)

All courses are in English ? Estos son los cursos con cupones gratuitos que me han parecido más interesantes y existen en la actualidad dentro de la plataforma Online de Udemy. Los contenidos en los que están organizados se reparten en: las criptomonedas, el diseño gráfico, la programación y el diseño web, ofimática, productividad, marketing y SEO, las redes y la robótica El listado final se ¡SEGUIR LEYENDO!

Mejores cursos de introducción a la programación

Muchos de estos cursos ya están incluidos en nuestro recopilatorio de cursos en español, allí podrás encontrarlos ordenados por temáticas y navegación de botones. En este otro enlace, podrás encontrar libros. Si lo que deseas es aprender a programar, no dejes de investigar más en profundidad alrededor de toda la web; y también, puedes investigar entre los cientos de recursos gratis que te ofrece Ciberninjas. A ¡SEGUIR LEYENDO!

Deja un comentario

Salir de la versión móvil