2012-04-15 5 views
4

Я пытаюсь скомпилировать расширение C++ для Ruby, и компиляция не возвращает ошибку, но, похоже, она не компилируется правильно. Что я делаю не так?Компиляция Ruby C++ Extension

У меня есть главной CPP сценарий foo.cpp:

#include <iostream> 
#include <ruby.h> 
extern "C" 

VALUE cFoo; 
void Init_foo(){cFoo = rb_define_class("Foo", rb_cObject);} 

и extconf.rb:

require "mkmf" 
$libs += " -lstdc++ " 
create_makefile("foo") 

и в директории этих файлов я сделал

$ ruby extconf.rb 
creating Makefile 
$ make 
compiling foo.cpp 
linking shared-object foo.so 
$ ls 
Makefile extconf.rb foo.cpp foo.o foo.so 

Затем, я ве Рубин сценарий test.rb:

#!/usr/bin/env ruby 
require "path_to_this_directory/foo" 

и я бегу test.rb. Он возвращает ошибку:

... in `require': .../foo.so: undefined symbol: cFoo - .../foo.so (LoadError) 

Что я делаю неправильно?

Environment

  • ОС: Ubuntu Linux 11,10
  • Ruby: 1.9.3

ответ

1

Вы объявляя, что cFoo существует:

extern "C" 

VALUE cFoo; 
никогда

но вы определите его. Высказывание extern "C" blahblah просто говорит, что blahblah существует, что он внешне видим и что его имя не будет искажено (т. Е. Связь «C»), но объявление extern фактически не определяет ничего; extern говорит, что что-то существует, но оно не создает его.

Ваш C++ должен выглядеть следующим образом:

#include <iostream> 
#include <ruby.h> 

extern "C" VALUE cFoo; 
extern "C" void Init_foo(); 

VALUE cFoo; 
void Init_foo(){cFoo = rb_define_class("Foo", rb_cObject);} 

Вам нужно два extern "C" сказать C++ компилятор, чтобы оставить имена в покое, а затем отдельные определения для символов. Вы также можете сказать следующее:

#include <iostream> 
#include <ruby.h> 

extern "C" VALUE cFoo; 

VALUE cFoo; 
extern "C" void Init_foo(){cFoo = rb_define_class("Foo", rb_cObject);} 

Я не уверен, что вторая версия является стандартным C++ или расширением GCC.

Я не являюсь человеком на С ++, поэтому, надеюсь, я не слишком плохо следил за терминологией.