gpt4 book ai didi

带有外部库的 C++ Ruby 扩展

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:36:18 24 4
gpt4 key购买 nike

我今天开始了一个小实验:我编写了一个依赖于其他一些库(ALGLIB、Eigen、内部工具)的 C++ 类,我想为该类创建一个 Ruby 包装器。我目前正在使用 Rice要做到这一点。首先,我为我的类编写了一个非常简单的 C++ 包装器:

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

除链接外一切正常。显然库的头文件是包含的,否则编译不了。但是当我在 Ruby 中运行一个小测试程序(“require “cmlp”;mlp = MLP.new”)时,它没有找到符号 _ZN6LoggerC1ENS_6TargetESs,它是 libtools(枚举)的一部分。这是我构建 C++ 扩展并执行测试程序时发生的情况:

$ 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?我感谢每一个提示。

编辑:好的,我更改了 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) $@

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) $@
$(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)



$(OBJS): ruby.h defines.h

最佳答案

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

可能是问题所在。我会在这里尝试绝对路径,我可以想象 pwd 与您在运行 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('libtools')

通过

have_library('tools') or raise

同样,“lib”被省略了。

如果还是不能解决问题,请贴出`ruby extconf.rb'生成的Makefile。

关于带有外部库的 C++ Ruby 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9251554/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com