1

So right now I'm just trying out C/C++ extensions in Ruby and I'm having troubles while using the rake-compile gem. Right now all I'm trying to do is define a module, and it won't load the Init_* function because it says the symbol is undefined. But when I examine the .so file it's clearly listed in the symbol table:

nm -gC RSFML.so                                 

0000000000201038 B __bss_start
                 w __cxa_finalize
0000000000201038 D _edata
0000000000201050 B _end
0000000000000744 T _fini
                 w __gmon_start__
00000000000005e0 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
                 U rb_define_module
0000000000201040 B RSFML
0000000000201048 B RSFML_Window
0000000000000725 T Init_RSFML()

Here's the error I get from the IRB:

irb -r ./lib/RSFML                      
/home/z/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require':LoadError: /home/z/Programming/ruby/RSFML-Gem/lib/RSFML.so: undefined symbol: Init_RSFML - /home/z/Programming/ruby/RSFML-Gem/lib/RSFML.so

I'm incredibly confused, and there doesn't seem to be much information on the matter of C extensions. Maybe there's something I'm missing? I have no idea.

SeedyROM
  • 2,203
  • 1
  • 18
  • 22

1 Answers1

4

Ruby can't find Init_RFSML since the name of the function is actually _Z10Init_RSFMLv (drop the -C option to disable name demangling; the actual name might also vary depending on the used compiler).

So you have to declare Init_* functions with C linkage which doesn't mangle names. In C++ this is done with extern "C" which is explained more thoroughly here.

cremno
  • 4,672
  • 1
  • 16
  • 27
  • So now that I've sorted that out, how exactly can I call C++ functions and declare objects from a C++ library? Since when I include the file, all the symbols get mangled and the functions expect them to be extern "C"'d. Or is just not possible, and I should give up for the night (haha) – SeedyROM Nov 12 '15 at 02:03
  • 1
    @Rust: Is this a new issue or do you need additional information about this one? Usually you only have to use `extern "C"` with the entry point (`Init_*`). If it's a new one, you might want to consider asking a new question (including any error messages and perhaps relevant source code). – cremno Nov 12 '15 at 02:36