2012-02-12 14 views
5

Bugün biraz deneme başlattım: Bazı kütüphanelere (ALGLIB, Eigen, iç araçlar) bağlı bir C++ sınıfı yazdım ve bu sınıf için bir Ruby sarıcı oluşturmak istedim. Bunu yapmak için şu anda Rice kullanıyorum.C++ Harici Kütüphanelerle Yakut Eklenti

// @file MLPWrapper.h 
#pragma once 

#include "mlp/MLP.h" 
#include <ruby.h> 

class MLPWrapper 
{ 
    MLP mlp; // <- my C++ class 
public: 
    ... 
    void fit() 
    { 
    ... 
    mlp.fit(stop); 
    } 
}; 

kütüphanenin cpp dosyası şudur: Önce benim sınıf için çok basit bir C++ sarıcı yazdı

// @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<MLPWrapper> rb_cMLPWrapper = define_class<MLPWrapper>("MLP") 
     .define_constructor(Constructor<MLPWrapper>()) 
     ... 
     .define_method("fit", &MLPWrapper::fit); 
} 

Ve bu extconf.rb geçerli:

require "mkmf-rice" 

$CFLAGS << "-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") 

Herşey Bağlama dışında gayet iyi çalışıyor. Açıkçası, kütüphanelerin başlık dosyaları dahil edilmiştir, aksi halde derleme yapılmaz. Ancak, Ruby'de biraz test programı çalıştırdığımda ("cmlp"; mlp = MLP.new "), libtools'un (bir enum) parçası olan _ZN6LoggerC1ENS_6TargetESs simgesini bulamaz.

$ 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 

kütüphaneler bütün (...) add_library() CMake ile derlenmiş ve

../../build/src/tools/libtools.so 
../../build/external/libraries/alglib/cpp/src/libalglib.so 
../../build/external/libraries/CMA-ESpp/cma-es/libcmaes.so 

I yer almaktadır: Bu benim C++ uzantısı oluşturmak ve test programı çalıştırmak ne olur Bu sorunu kendi başıma nasıl çözeceğimi bilmiyorum ve sorunum için yararlı bir doküman bulamadım. Bu extconf.rb'yi nasıl düzeltirim? Her ipucunu takdir ediyorum.

düzenleme:

require "rubygems" 
require "mkmf-rice" 

BASE_DIR = "/bla/" 

$CFLAGS << " -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") 

oluşturulan Makefile geçerli::

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) [email protected] 

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 $< 

.cxx.o: 
    $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $< 

.cpp.o: 
    $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $< 

.C.o: 
    $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $< 

.c.o: 
    $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< 

$(DLLIB): $(OBJS) Makefile 
    @-$(RM) [email protected] 
    $(LDSHARED) -o [email protected] $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) 



$(OBJS): ruby.h defines.h 

cevap

4
../../build/src/tools/libtools.so 
../../build/external/libraries/alglib/cpp/src/libalglib.so  
../../build/external/libraries/CMA-ESpp/cma-es/libcmaes.so 

sorun olabilir Tamam, extconf.rb değişti. Mutlak yolları burada deneyeceğim, pwd'nin ruby extconf.rb'u çalıştırırken beklediğinizden farklı olduğunu hayal edebiliyorum. Ayrıca , ben Yani

dir_config('libs', HEADER_DIRS, LIB_DIRS) 

dir_config('tools', '<Path to include dir>', '<Path to lib dir>') 
dir_config('alglib', '<Path to include dir>', '<Path to lib dir>') 

Not değiştirilmesi gerektiğini lider 'lib' atlanmış gerektiğini. Eğer bağlantısını istediğiniz her kütüphane için bir dir_config girişi ihtiyaç varsayalım tıpkı, -l linker seçeneğinde yaptığınız gibi. Eğer bir kütüphane bulunduğunu kesinlikle emin olmak istiyorsanız Sonra, Yine, 'lib' atlanırsa

have_library('tools') or raise 

tarafından

have_library('libtools') 

değiştirin.

Sorunu hala çözemiyorsanız, lütfen "ruby extconf.rb" tarafından oluşturulan Makefile dosyasını gönderin.

+0

Tamam, önerileriniz bana biraz yardımcı oldu. Ruby kütüphaneleri şimdi bulur, ancak test komut dosyasını çalıştırdığımda yüklenmez. Bu sonuç: _./cmlp.so: libcmaes.so: paylaşılan nesne dosyasını açamıyor: /usr/lib/ruby/vendor_ruby/1.8/ adresinden böyle bir dosya veya dizin yok - ./cmlp.so (LoadError) rubygems/custom_require.rb: 36: ' 'dan' test.rb 'ye gereksinim duyar: 2_ Makefile'yi ekledim. – alfa

+0

LD_LIBRARY_PATH ayarlandığında, statik kitaplıklarla bağlantı kurmaya çalıştığınızda aşağıdaki hata oluşur: _/usr/bin/ld:/bla/build/external/library/CMA-ESpp/cma-es/libcmaes. a (timings.cpp.o): tanımlanmamış bir sembol olan R_X86_64_PC32 sembolü 'clock @@ GLIBC_2.2.5 ', paylaşılan bir nesne oluşturulurken kullanılamaz; -FPIC_ ile yeniden derleme Bu sorunu çözmek için ortam değişkenini belirlemekten daha iyi bir yol var mı? – alfa

+2

Evet, linker'ınızın 'rpath' seçeneğini doğru olarak ayarladıysanız ([ayrıca bakınız] (http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html)) LD_LIBRARY_PATH. Pirinç olmadan, "ruby extconf.rb --with-tools-lib-dir = --with-alglib-dir = '" dediğinizde bu ayarın Makefile'de doğru şekilde ayarlandığını doğrulayabilirim. Belki bunu denersin? Çalışma zamanı arama yolu doğru ayarlanmışsa oluşturulan Makefile'yi kontrol edin. Bir başka seçenek de elbette kütüphanelerinizi standart arama yollarından birine kurmanızdır. – emboss