Я создаю простое расширение C для модуля Ruby, и у меня возникают проблемы с segfault, когда я вызываю другую функцию C внутри моего расширения. Основной поток выполнения выглядит следующим образом:
- Я создаю класс Ruby и вызываю для него метод экземпляра, который
- Вызывает метод C в моем расширении, которое
- Вызывает другую функцию C, в отдельном файле, но скомпилированную OK
Это последний прыжок, который кажется сломанным. Я был в состоянии воспроизвести проблему почти без функциональности, кроме вызовов функций. У меня есть стандартный extconf.rb
, скомпилируйте его с помощью прямого Make, и он вызывает ошибку при вызове encrypt()
. При запуске я выполняю следующие команды:
$ ruby extconf.rb
$ make clean
$ make
$ ruby -r des -e 'puts DES.new.encrypt!'
Выход:
creating Makefile
/usr/bin/gcc-4.2 -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I/opt/local/lib/ruby/1.8/i686-darwin10 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -fno-common -std=c99 -arch x86_64 -c calc.c
/usr/bin/gcc-4.2 -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I/opt/local/lib/ruby/1.8/i686-darwin10 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -fno-common -std=c99 -arch x86_64 -c deslib.c
/usr/bin/gcc-4.2 -dynamic -bundle -undefined suppress -flat_namespace -o calc.bundle calc.o deslib.o -L. -L/opt/local/lib -L/opt/local/lib -L. -L/opt/local/lib -arch x86_64 -arch x86_64 -lruby -lpthread -ldl -lobjc
About to do C encrypt...
./des.rb:42: [BUG] Segmentation fault
ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-darwin10]
zsh: abort ruby -r des -e 'puts DES.new.encrypt!'
Класс Ruby:
class D
def encrypt!
self.encrypted = Calc.encrypt(0,0,0)
return self.encrypted
end
end
Модуль Calc:
#include "ruby.h"
#include "cryptlib.h"
VALUE Calc = Qnil;
void Init_calc();
VALUE method_encrypt(VALUE self, VALUE m, VALUE k, VALUE n);
void Init_calc() {
Calc = rb_define_module("Calc");
rb_define_method(Calc, "encrypt", method_encrypt, 3);
}
VALUE method_encrypt(VALUE self, VALUE m, VALUE k, VALUE n) {
uint64_t message = NUM2ULONG(m);
uint64_t key = NUM2ULONG(k);
int iters = NUM2INT(n);
printf("About to do C encrypt...\n");
uint64_t ciphertext = encrypt(message, key, iters);
printf("Done with C encrypt\n");
return ULONG2NUM(ciphertext);
}
cryptlib.h:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
uint64_t encrypt(uint64_t message, uint64_t key, int iters);
cryptlib.c:
#include "cryptlib.h"
uint64_t encrypt(uint64_t message, uint64_t key, int iters) {
return 0;
}
Почему это так плохо? Я запускаю ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-darwin10]
на MacBook Pro, скомпилированном из MacPorts менее часа назад. Мой gcc --version
:
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)