4

Ruby用のc++拡張機能をコンパイルしようとしていますが、コンパイルでエラーが返されませんが、正しくコンパイルされていないようです。私は何が間違っているのですか?

私はメインの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

次に、Rubyスクリプトtest.rbがあります。

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

そして私は実行しtest.rbます。エラーを返します:

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

私は何が間違っているのですか?

環境

  • OS:Ubuntu Linux 11.10
  • Ruby:1.9.3
4

1 に答える 1

1

あなたはそれcFooが存在することを宣言しています:

extern "C"

VALUE cFoo;

しかし、あなたはそれを決して定義しません。それは存在し、外部からは見え、名前は変更されない(つまり、「C」リンケージ)とextern "C" blahblahだけ言っていますが、宣言は実際には何も定義していません。何かが存在すると言いますが、それはそれを実現しません。blahblahexternextern

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++コンパイラに指示するには2つ必要です。あなたはこれを言うこともできます:

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

extern "C" VALUE cFoo;

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

2番目のバージョンが標準のC++なのかGCC拡張版なのかわかりません。

私はC++の人間ではないので、用語をひどく乱用していないことを願っています。

于 2012-04-16T00:21:10.023 に答える