Extending Ruby using C++ and Rice
- From:
- Lea Savage
- Date:
- 2010-04-19 @ 09:36
Hi All,
I submitted a question to the following forum
http://www.ruby-forum.com/topic/208124#905786 with regards to an issue I
am experiencing with extending ruby with Rice. I am not sure is this is a
Rice specific issue but I am taking the suggestion from Jason
Roelofs (see forum) to email this list.
My original post was:
Hi,
I am trying to extend Ruby and my current implementation is using C++ and
Rice (http://rice.rubyforge.org/main.html).
Mac OS X 10.5.8
Ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
I have completed the following steps as shown in Rice to create a cpp
class (my_test.cpp)
#include "rice/Class.hpp"
#include "rice/Data_Type.hpp"
#include "rice/Constructor.hpp"
#include "MyTest.h"
using namespace Rice;
extern "C"
void Init_my_test()
{
define_class<MyTest>("MyTest").
define_constructor(Constructor<MyTest>()).
define_method("read", &MyTest::read);
}
Here are my h and cpp files for MyTest
*** HEADER FILE ***
#ifndef __MyTest_h
#define __MyTest_h
#include <string>
#include "XternalDebug.hpp"
class MyTest
{
public:
MyTest() {};
virtual ~MyTest(void){
SX::Terminate();
SXMP::Terminate();
}
std::string read(std::string filename);
};
#endif
*** CPP FILE ***
#include "MyTest.h"
extern "C" std::string MyTest::read(std::string filename)
{
if(SXMP::Initialize())
{
// Must initialize SX before we use it
if (SX::Initialize())
{
std::string status = "";
bool ok;
SX myFile;
myFile.OpenFile(filename, UnknownFile, opts);
std::string buffer;
myFile.Get(&buffer);
return buffer;
}
}
return NULL;
}
SX and SXMP are taken from another library called libXternalDebug.a
My extconf.rb file looks as follows:
require 'rubygems'
require 'mkmf-rice'
$CPPFLAGS << ' -DMAC_ENV=1'
have_library("stdc++")
dir_config("xtoolkit")
have_library("XternalDebug")
create_makefile("my_test")
I pass the following arguments to extconf.rb
#ARCHFLAGS="-arch i386" ruby extconf.rb
--with-xtoolkit-include=/Users/<username>/xtoolkit/public/include
--with-xtoolkit-lib=/Users/<username>/xtoolkit/public/libraries
$ ARCHFLAGS="-arch i386" ruby extconf.rb
--with-xtoolkit-include=/Users/<username>/xtoolkit/public/include
--with-xtoolkit-lib=/Users/<username>/xtoolkit/public/libraries
checking for main() in -lrice... yes
checking for main() in -lstdc++... yes
checking for main() in -lX... yes
creating Makefile
I then run make:
$ makeg++ -I. -I.
-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0
-I. -I/Users/<username>/xtoolkit/public/include
-I/Library/Ruby/Gems/1.8/gems/rice-1.3.1/ruby/lib/include -DMAC_ENV=1
-fno-common -arch i386 -Os -pipe -fno-common -Wall -g -c my_test.cpp
g++ -I. -I.
-I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0
-I. -I/Users/<username>/xtoolkit/public/include
-I/Library/Ruby/Gems/1.8/gems/rice-1.3.1/ruby/lib/include -DMAC_ENV=1
-fno-common -arch i386 -Os -pipe -fno-common -Wall -g -c MyTest.cpp
g++ -arch i386 -pipe -bundle -undefined dynamic_lookup -o my_test.bundle
my_test.o MyTest.o -L.
-L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib
-L/Users/<username>/xtoolkit/public/libraries -L. -arch i386
-L/Library/Ruby/Gems/1.8/gems/rice-1.3.1/ruby/lib/lib -lXternalDebug
-lstdc++ -lrice -lruby -lpthread -ldl -lm
(please note i have removed my username intentionally from the above paths)
I then have the following ruby test:
require 'my_test'
require 'test/unit'
class TestTest < Test::Unit::TestCase
def test_test
t = MyTest.new
assert_equal(Object, MyTest.superclass)
assert_equal(MyTest, t.class)
end
end
When I try to run this I get the following error:
$ ruby testtest.rb
Loaded suite testtest
Started
.
Finished in 0.000476 seconds.
1 tests, 2 assertions, 0 failures, 0 errors
dyld: lazy symbol binding failed: Symbol not found: __ZN9TSXMISsE9TerminateEv
Referenced from: /Users/<username>/tests/rice_test2/my_test.bundle
Expected in: dynamic lookup
dyld: Symbol not found: __ZN9TSXISsE9TerminateEv
Referenced from: /Users/<username>/tests/rice_test2/my_test.bundle
Expected in: dynamic lookup
Trace/BPT trap
Does anyone know what I am doing wrong or what I am missing to get these
errors? Do I need to include this external library in a particular
directory for ruby to discover?
Any help is much appreciated.
Lea
-- end of original post --
I have just tried his suggestion to remove extern C from my cpp class and
I receive the following issue when running my test:
$ ruby testtest.rb
./my_test.bundle: dlsym(0x221a60, Init_my_test): symbol not found -
./my_test.bundle (LoadError)
from testtest.rb:1
I have also included the .a library in my directory to try and resolve the
load issues I am experiencing but still receiving the above issue.
Additionally I have tried to update the dyld_library_path:
DYLD_LIBRARY_PATH=/Users/<username>/xtoolkit/public/libraries:$DYLD_LIBRARY_PATH
export DYLD_LIBRARY_PATH
Does anyone know what I am doing wrong?
Thanks in advance,
Lea
Re: [rice] Extending Ruby using C++ and Rice
- From:
- Ammar Ali
- Date:
- 2010-04-19 @ 10:12
On 4/19/10 12:36 PM, Lea Savage wrote:
> I have also included the .a library in my directory to try and resolve
> the load issues I am experiencing but still receiving the above issue.
>
> Additionally I have tried to update the dyld_library_path:
> DYLD_LIBRARY_PATH=/Users/<username>/xtoolkit/public/libraries:$DYLD_LIBRARY_PATH
> export DYLD_LIBRARY_PATH
Archive library (.a) files do not get dynamically loaded, you need the
.dyld version somewhere in the load path. If it doesn't exist, or you
want to statically link it, try to include the full path to the .a file
in the link step.
HTH,
Ammar