我正在尝试为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)
我做错了什么?
环境
答案 0 :(得分: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扩展。
我不是一个C ++人,所以我希望我没有把这个术语搞得太严厉。