2012-02-12 16 views
5

मैंने आज थोड़ा प्रयोग शुरू किया: मैंने एक सी ++ वर्ग लिखा जो कुछ अन्य पुस्तकालयों (एएलजीएलबी, ईजिन, आंतरिक उपकरण) पर निर्भर करता है और मैं उस वर्ग के लिए रूबी रैपर बनाना चाहता था। मैं वर्तमान में ऐसा करने के लिए Rice का उपयोग कर रहा हूं।सी ++ बाहरी पुस्तकालयों के साथ रूबी एक्सटेंशन

// @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); 
    } 
}; 

लाइब्रेरी की cpp फ़ाइल यह है:: सबसे पहले मैं अपने वर्ग के लिए एक बहुत ही सरल सी ++ आवरण लिखा

// @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); 
} 

और यह extconf.rb है:

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

सब कुछ लिंकिंग को छोड़कर ठीक काम करता है। स्पष्ट रूप से पुस्तकालयों की शीर्षलेख फ़ाइलें शामिल हैं, अन्यथा यह संकलित नहीं होगी। लेकिन जब मैं रूबी में थोड़ा परीक्षण प्रोग्राम चलाता हूं ("सीएमएलपी" की आवश्यकता होती है "; mlp = mLP.new") इसे _ZN6LoggerC1ENS_6TargetESs प्रतीक नहीं मिलता है, जो libtools (en enum) का हिस्सा है।

$ 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 

पुस्तकालयों सभी CMake के साथ संकलित किए जाते हैं (add_library (...)) और

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

मैं स्थित हैं: यह जब मैं सी ++ विस्तार निर्माण और परीक्षण कार्यक्रम क्रियान्वित क्या होता है इस समस्या को हल करने के बारे में नहीं जानते और मुझे अपनी समस्या के लिए कोई उपयोगी दस्तावेज नहीं मिला। मैं इस extconf.rb को कैसे ठीक करूं? मैं हर संकेत की सराहना करता हूं।

संपादित करें:

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

उत्पन्न Makefile है:

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 

उत्तर

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

समस्या हो सकती है ठीक है, मैं extconf.rb बदल दिया है। मैं यहां पूर्ण पथों का प्रयास करूंगा, मैं कल्पना कर सकता हूं कि ruby extconf.rb चलाते समय पीडब्ल्यूडी आपके अपेक्षा से अलग है। इसके अलावा, मैं आप प्रत्येक पुस्तकालय आप में लिंक करना चाहते हैं के लिए एक dir_config प्रवेश की जरूरत है मान। तो

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>') 

नोट प्रतिस्थापित किया जाना चाहिए कि प्रमुख 'lib' छोड़ दिया जाना चाहिए , जैसा कि आप -l लिंकर विकल्प में करेंगे। इसके बाद, अगर आप पूरी तरह यकीन है कि एक पुस्तकालय पाया जाता है होना चाहता हूँ, द्वारा

have_library('tools') or raise 

फिर, 'lib' छोड़ दिया जाता है

have_library('libtools') 

बदलें।

यदि आप अभी भी समस्या का समाधान नहीं कर सकते हैं, तो कृपया 'रूबी extconf.rb' द्वारा उत्पन्न मेकफ़ाइल पोस्ट करें।

+0

ठीक है, आपके सुझावों ने मुझे थोड़ा सा मदद की। रुबी अब पुस्तकालयों को पाता है लेकिन जब मैं टेस्ट स्क्रिप्ट निष्पादित करता हूं तो वे लोड नहीं होते हैं। यह परिणाम है: _./cmlp.so: libcmaes.so: साझा ऑब्जेक्ट फ़ाइल नहीं खोल सकता: ऐसी कोई फ़ाइल या निर्देशिका नहीं - ./cmlp.so (LoadError) /usr/lib/ruby/vendor_ruby/1.8/ से rubygems/custom_require।आरबी: 36: test.rb से 'आवश्यकता' में: 2_ मैंने मेकफ़ाइल संलग्न किया। – alfa

+0

जब मैं एलडी_LIBRARY_PATH सेट करता हूं, यह स्थिर पुस्तकालयों से जुड़ने का प्रयास करता है, तो निम्न त्रुटि होती है: _/usr/bin/ld:/bla/build/external/पुस्तकालय/सीएमए-ईएसपीपी/सीएमए-एसएस/libcmaes। a (timings.cpp.o): अपरिभाषित प्रतीक 'घड़ी @@ GLIBC_2.2.5' के विरुद्ध स्थानांतरित R_X86_64_PC32 साझा ऑब्जेक्ट बनाते समय उपयोग नहीं किया जा सकता है; -fPIC_ के साथ पुन: संकलित करें क्या पर्यावरण परिवर्तक को सेट करने से इस समस्या को हल करने का कोई बेहतर तरीका है? – alfa

+2

हां, यदि आप अपने लिंकर के 'rpath' विकल्प को सही तरीके से सेट करते हैं ([यह भी देखें] (http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html)), इसकी कोई आवश्यकता नहीं है एलडी_LIBRARY_PATH सेट करें। चावल के बिना, मैं पुष्टि कर सकता हूं कि यह आपके मेकफ़ाइल में सही ढंग से सेट किया गया है जब आप 'रूबी extconf.rb-with-tools-lib-dir = --with-alglib-dir = ' कहते हैं। शायद आप इसे आज़माएं? रनटाइम खोज पथ सही ढंग से सेट किया गया है, तो जेनरेट मेकफ़ाइल में जांचें। एक और विकल्प मानक पुस्तकालयों में से एक में बस अपने पुस्तकालयों को स्थापित करने के लिए है। – emboss

संबंधित मुद्दे