Note that there are some explanatory texts on larger screens.

plurals
  1. POC++ Ruby Extension with External Libraries
    primarykey
    data
    text
    <p>I started a little experiment today: I wrote a C++ class which depends on some other libraries (ALGLIB, Eigen, internal tools) and I wanted to create a Ruby wrapper for that class. I'm currently using <a href="http://rice.rubyforge.org/" rel="nofollow">Rice</a> to do that. First I wrote a very simple C++ wrapper for my class:</p> <pre><code>// @file MLPWrapper.h #pragma once #include "mlp/MLP.h" #include &lt;ruby.h&gt; class MLPWrapper { MLP mlp; // &lt;- my C++ class public: ... void fit() { ... mlp.fit(stop); } }; </code></pre> <p>The library's cpp-file is this:</p> <pre><code>// @file cmlp.cpp #include "rice/Data_Type.hpp" #include "rice/Constructor.hpp" #include "MLPWrapper.h" using namespace Rice; extern "C" void Init_cmlp() { Data_Type&lt;MLPWrapper&gt; rb_cMLPWrapper = define_class&lt;MLPWrapper&gt;("MLP") .define_constructor(Constructor&lt;MLPWrapper&gt;()) ... .define_method("fit", &amp;MLPWrapper::fit); } </code></pre> <p>And this is the extconf.rb:</p> <pre><code>require "mkmf-rice" $CFLAGS &lt;&lt; "-O3" HEADER_DIRS = [ "..", "../../external/libraries/eigen-eigen-3.0.1", "../../external/libraries/alglib/cpp/src", "../../external/libraries/CMA-ESpp" ] LIB_DIRS = [ "../../build/external/libraries/alglib/cpp/src", "../../build/external/libraries/CMA-ESpp/cma-es", "../../build/src/tools" ] dir_config("libs", HEADER_DIRS, LIB_DIRS) have_library("libtools") have_library("libalglib") create_makefile("cmlp") </code></pre> <p>Everything works fine except linking. Obviously the header files of the libraries are included, otherwise it would not compile. But when I run a little test program ("require "cmlp"; mlp = MLP.new") in Ruby it does not find the symbol _ZN6LoggerC1ENS_6TargetESs, which is part of libtools (an enum). This is what happens when I build the C++ extension and execute the test program:</p> <pre><code>$ ruby extconf.rb checking for main() in -lrice... yes checking for main() in -llibtools... no checking for main() in -llibalglib... no checking for main() in -llibcmaes... no creating Makefile $ make g++ -I. -I. -I/usr/lib/ruby/1.8/x86_64-linux -I. -I.. -I../../external/libraries/eigen-eigen-3.0.1 -I../../external/libraries/alglib/cpp/src -I../../external/libraries/CMA-ESpp -I/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/include -fPIC -fno-strict-aliasing -g -g -O2 -fPIC -O3 -Wall -g -c cmlp.cpp g++ -shared -o cmlp.so cmlp.o -L. -L/usr/lib -L../../build/external/libraries/alglib/cpp/src -L../../build/external/libraries/CMA-ESpp/cma-es -L../../build/src/tools -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic -L/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/lib -lrice -lruby1.8 -lpthread -lrt -ldl -lcrypt -lm -lc $ ruby test.rb ruby: symbol lookup error: ./cmlp.so: undefined symbol: _ZN6LoggerC1ENS_6TargetESs </code></pre> <p>The libraries are all compiled with CMake (add_library(...)) and are located at</p> <pre><code>../../build/src/tools/libtools.so ../../build/external/libraries/alglib/cpp/src/libalglib.so ../../build/external/libraries/CMA-ESpp/cma-es/libcmaes.so </code></pre> <p>I don't know how to solve this problem on my own and I could not find any helpful documentation for my problem. How do i fix this extconf.rb? I appreciate every hint.</p> <p>edit: OK, I changed the extconf.rb:</p> <pre><code>require "rubygems" require "mkmf-rice" BASE_DIR = "/bla/" $CFLAGS &lt;&lt; " -O3" dir_config("tools", [BASE_DIR + "src", BASE_DIR + "external/libraries/eigen-eigen-3.0.1"], BASE_DIR + "build/src/tools") unless have_library("tools") abort "tools are missing. please compile tools" end dir_config("alglib", BASE_DIR + "external/libraries/alglib/cpp/src", BASE_DIR + "build/external/libraries/alglib/cpp/src") unless have_library("alglib") abort "alglib is missing. please compile alglib" end dir_config("cmaes", BASE_DIR + "external/libraries/CMA-ESpp", BASE_DIR + "build/external/libraries/CMA-ESpp/cma-es") unless have_library("cmaes") abort "cmaes is missing. please compile cmaes" end create_makefile("cmlp") </code></pre> <p>The generated Makefile is:</p> <pre><code>SHELL = /bin/sh #### Start of system configuration section. #### srcdir = . topdir = /usr/lib/ruby/1.8/x86_64-linux hdrdir = $(topdir) VPATH = $(srcdir):$(topdir):$(hdrdir) exec_prefix = $(prefix) prefix = $(DESTDIR)/usr sharedstatedir = $(prefix)/com mandir = $(prefix)/share/man psdir = $(docdir) oldincludedir = $(DESTDIR)/usr/include localedir = $(datarootdir)/locale bindir = $(exec_prefix)/bin libexecdir = $(prefix)/lib/ruby1.8 sitedir = $(DESTDIR)/usr/local/lib/site_ruby htmldir = $(docdir) vendorarchdir = $(vendorlibdir)/$(sitearch) includedir = $(prefix)/include infodir = $(prefix)/share/info vendorlibdir = $(vendordir)/$(ruby_version) sysconfdir = $(DESTDIR)/etc libdir = $(exec_prefix)/lib sbindir = $(exec_prefix)/sbin rubylibdir = $(libdir)/ruby/$(ruby_version) docdir = $(datarootdir)/doc/$(PACKAGE) dvidir = $(docdir) vendordir = $(libdir)/ruby/vendor_ruby datarootdir = $(prefix)/share pdfdir = $(docdir) archdir = $(rubylibdir)/$(arch) sitearchdir = $(sitelibdir)/$(sitearch) datadir = $(datarootdir) localstatedir = $(DESTDIR)/var sitelibdir = $(sitedir)/$(ruby_version) CC = gcc LIBRUBY = $(LIBRUBY_SO) LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME) LIBRUBYARG_STATIC = -lruby1.8-static RUBY_EXTCONF_H = CFLAGS = -fPIC -fno-strict-aliasing -g -g -O2 -fPIC $(cflags) -O3 INCFLAGS = -I. -I. -I/usr/lib/ruby/1.8/x86_64-linux -I. DEFS = CPPFLAGS = -I/bla/external/libraries/CMA-ESpp -I/bla//external/libraries/alglib/cpp/src -I//bla/src -I/bla/external/libraries/eigen-eigen-3.0.1 -I/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/include CXXFLAGS = $(CFLAGS) -Wall -g ldflags = -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic -L/var/lib/gems/1.8/gems/rice-1.4.3/ruby/lib/lib dldflags = archflag = DLDFLAGS = $(ldflags) $(dldflags) $(archflag) LDSHARED = g++ -shared AR = ar EXEEXT = RUBY_INSTALL_NAME = ruby1.8 RUBY_SO_NAME = ruby1.8 arch = x86_64-linux sitearch = x86_64-linux ruby_version = 1.8 ruby = /usr/bin/ruby1.8 RUBY = $(ruby) RM = rm -f MAKEDIRS = mkdir -p INSTALL = /usr/bin/install -c INSTALL_PROG = $(INSTALL) -m 0755 INSTALL_DATA = $(INSTALL) -m 644 COPY = cp #### End of system configuration section. #### preload = CXX = g++ libpath = . $(libdir) /bla/external/libraries/CMA-ESpp/cma-es /bla/build/external/libraries/alglib/cpp/src /bla/build/src/tools LIBPATH = -L. -L$(libdir) -L/bla/build/external/libraries/CMA-ESpp/cma-es -L/bla/build/external/libraries/alglib/cpp/src -L/bla/build/src/tools DEFFILE = CLEANFILES = mkmf.log DISTCLEANFILES = extout = extout_prefix = target_prefix = LOCAL_LIBS = LIBS = -lcmaes -lalglib -ltools -lrice -lruby1.8 -lpthread -lrt -ldl -lcrypt -lm -lc SRCS = cmlp.cpp OBJS = cmlp.o TARGET = cmlp DLLIB = $(TARGET).so EXTSTATIC = STATIC_LIB = BINDIR = $(bindir) RUBYCOMMONDIR = $(sitedir)$(target_prefix) RUBYLIBDIR = $(sitelibdir)$(target_prefix) RUBYARCHDIR = $(sitearchdir)$(target_prefix) TARGET_SO = $(DLLIB) CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak all: $(DLLIB) static: $(STATIC_LIB) clean: @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) distclean: clean @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) realclean: distclean install: install-so install-rb install-so: $(RUBYARCHDIR) install-so: $(RUBYARCHDIR)/$(DLLIB) $(RUBYARCHDIR)/$(DLLIB): $(DLLIB) $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) install-rb: pre-install-rb install-rb-default install-rb-default: pre-install-rb-default pre-install-rb: Makefile pre-install-rb-default: Makefile $(RUBYARCHDIR): $(MAKEDIRS) $@ site-install: site-install-so site-install-rb site-install-so: install-so site-install-rb: install-rb .SUFFIXES: .c .m .cc .cxx .cpp .C .o .cc.o: $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $&lt; .cxx.o: $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $&lt; .cpp.o: $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $&lt; .C.o: $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $&lt; .c.o: $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $&lt; $(DLLIB): $(OBJS) Makefile @-$(RM) $@ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) $(OBJS): ruby.h defines.h </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload