मैंने आज थोड़ा प्रयोग शुरू किया: मैंने एक सी ++ वर्ग लिखा जो कुछ अन्य पुस्तकालयों (एएलजीएलबी, ईजिन, आंतरिक उपकरण) पर निर्भर करता है और मैं उस वर्ग के लिए रूबी रैपर बनाना चाहता था। मैं वर्तमान में ऐसा करने के लिए 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
ठीक है, आपके सुझावों ने मुझे थोड़ा सा मदद की। रुबी अब पुस्तकालयों को पाता है लेकिन जब मैं टेस्ट स्क्रिप्ट निष्पादित करता हूं तो वे लोड नहीं होते हैं। यह परिणाम है: _./cmlp.so: libcmaes.so: साझा ऑब्जेक्ट फ़ाइल नहीं खोल सकता: ऐसी कोई फ़ाइल या निर्देशिका नहीं - ./cmlp.so (LoadError) /usr/lib/ruby/vendor_ruby/1.8/ से rubygems/custom_require।आरबी: 36: test.rb से 'आवश्यकता' में: 2_ मैंने मेकफ़ाइल संलग्न किया। – alfa
जब मैं एलडी_LIBRARY_PATH सेट करता हूं, यह स्थिर पुस्तकालयों से जुड़ने का प्रयास करता है, तो निम्न त्रुटि होती है: _/usr/bin/ld:/bla/build/external/पुस्तकालय/सीएमए-ईएसपीपी/सीएमए-एसएस/libcmaes। a (timings.cpp.o): अपरिभाषित प्रतीक 'घड़ी @@ GLIBC_2.2.5' के विरुद्ध स्थानांतरित R_X86_64_PC32 साझा ऑब्जेक्ट बनाते समय उपयोग नहीं किया जा सकता है; -fPIC_ के साथ पुन: संकलित करें क्या पर्यावरण परिवर्तक को सेट करने से इस समस्या को हल करने का कोई बेहतर तरीका है? – alfa
हां, यदि आप अपने लिंकर के 'rpath' विकल्प को सही तरीके से सेट करते हैं ([यह भी देखें] (http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html)), इसकी कोई आवश्यकता नहीं है एलडी_LIBRARY_PATH सेट करें। चावल के बिना, मैं पुष्टि कर सकता हूं कि यह आपके मेकफ़ाइल में सही ढंग से सेट किया गया है जब आप 'रूबी extconf.rb-with-tools-lib-dir = --with-alglib-dir = ' कहते हैं। शायद आप इसे आज़माएं? रनटाइम खोज पथ सही ढंग से सेट किया गया है, तो जेनरेट मेकफ़ाइल में जांचें। एक और विकल्प मानक पुस्तकालयों में से एक में बस अपने पुस्तकालयों को स्थापित करने के लिए है। –
emboss