【问题标题】:Ruby Gems C extension example not workingRuby Gems C 扩展示例不起作用
【发布时间】:2015-09-15 03:45:34
【问题描述】:

我正在尝试按照本教程在 ruby​​ gems http://guides.rubygems.org/gems-with-extensions/ 中构建 c 扩展。

我有以下文件:

ext/my_malloc/extconf.rb

require "mkmf"

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

create_makefile "my_malloc/my_malloc"

ext/my_malloc/my_malloc.c

#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);
}

我执行以下操作来构建扩展:

$ 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"

但是,我在最后一个命令中收到以下错误:

/Users/Daniel/.rbenv/versions/2.1.6/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- my_malloc (LoadError)
from     
/Users/Daniel/.rbenv/versions/2.1.6/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'

注意,我使用的是 rbenv,我尝试过运行 rbenv rehash,而且我运行的是 2.1.6 版。

【问题讨论】:

  • -Ilib:ext -> -Ilib/ext?
  • 错误依旧

标签: ruby gem ruby-c-extension


【解决方案1】:

正确的shell命令是:

ruby -Iext/my_malloc -r my_malloc -e "p MyMalloc.new(5).free"

该代码还存在一些其他错误。正确

rb_raise(rb_eNoMemError, "unable to allocate %ld bytes", requested);

rb_raise(rb_eNoMemError, "unable to allocate %" PRIuSIZE " bytes", requested);

因为requested 的类型为size_t 而不是longPRIuSIZE 是非标准的,在"ruby/ruby.h" 中定义)。和

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

cMyMalloc = rb_define_class("MyMalloc", rb_cObject);

实际定义MyMalloc 类。

【讨论】:

  • 谢谢。仅供参考,更改为 PRIuSIZE 会在 make warning: data argument not used by format string [-Wformat-extra-args] 上引发警告。
  • 已修复。 %。字符丢失。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 2020-01-04
  • 1970-01-01
  • 2013-06-12
  • 2015-03-01
相关资源
最近更新 更多