R动态荷载“的;“未找到符号”;错误,即使是C++;代码构建良好 我有一个简单的C++程序,可以在Mac(小牛)上使用 CLAN++/COD>成功构建,但在使用 RCMD SLIB < /C>时失败,并在中加载 Dyn。 这是C++代码(存储在Simult.CPP)中,使用GuROMI优化器: #include "gurobi_c++.h" #include <iostream> void fxn() { GRBEnv env = GRBEnv(); // Create a Gurobi environment GRBModel colgen = GRBModel(env); // Create empty model object colgen.addVar(0, 1, 0.0, GRB_BINARY); // Add binary variable to model std::cout << "Hello world" << std::endl; } int main(int argc, char **argv) { fxn(); return 0; }

R动态荷载“的;“未找到符号”;错误,即使是C++;代码构建良好 我有一个简单的C++程序,可以在Mac(小牛)上使用 CLAN++/COD>成功构建,但在使用 RCMD SLIB < /C>时失败,并在中加载 Dyn。 这是C++代码(存储在Simult.CPP)中,使用GuROMI优化器: #include "gurobi_c++.h" #include <iostream> void fxn() { GRBEnv env = GRBEnv(); // Create a Gurobi environment GRBModel colgen = GRBModel(env); // Create empty model object colgen.addVar(0, 1, 0.0, GRB_BINARY); // Add binary variable to model std::cout << "Hello world" << std::endl; } int main(int argc, char **argv) { fxn(); return 0; },c++,r,gurobi,C++,R,Gurobi,我能够使用R CMD SHLIB成功编译: $ MAKEFLAGS="PKG_CXXFLAGS=-I/Library/gurobi562/mac64/include" R CMD SHLIB \ simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \ -stdlib=libstdc++ -lpthread -lm clang++ -I/Library/Frameworks/R.framework/Resour

我能够使用
R CMD SHLIB
成功编译:

$ MAKEFLAGS="PKG_CXXFLAGS=-I/Library/gurobi562/mac64/include" R CMD SHLIB \
  simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
  -stdlib=libstdc++ -lpthread -lm
clang++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG \
  -I/usr/local/include   -I/Library/gurobi562/mac64/include -fPIC  -mtune=core2 \
  -g -O2  -c simple.cpp -o simple.o
clang++ -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup \
  -single_module -multiply_defined suppress -L/usr/local/lib -L/usr/local/lib \
  -o simple.so simple.o -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
  -stdlib=libstdc++ -lpthread -lm -F/Library/Frameworks/R.framework/.. \
  -framework R -Wl,-framework -Wl,CoreFoundation
但是,
dyn.load(“simple.so”)
在R:

Error in dyn.load("simple.so") : 
  unable to load shared object '[path]/simple.so':
  dlopen([path]/simple.so, 6): Symbol not found: __ZN8GRBModel6addVarEdddcNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
  Referenced from: [path]/simple.so
  Expected in: flat namespace
 in [path]/simple.so
c++filt
,我可以看到缺少的符号是
GRBModel::addVar(double,double,double,char,std::\uu 1::basic\u string)
,它应该由我链接的一个Gurobi库提供

从以前的文章中,我发现这些“Symbol not found”错误通常是由于没有链接正确的库而发生的,但是我已经成功地编译并运行了
simple.cpp
,并且将相同的链接选项传递给
R CMD SHLIB

以下是我的
~/.R/Makevars
文件的内容:

CC=clang
CXX=clang++

Edit我认为问题可能与编译代码时使用的选项
-stdlib=libstdc++
有关。当我从第一个构建中删除此选项时(工作调用
clang++
),我得到的第一个链接器错误是:

Undefined symbols for architecture x86_64:
  "GRBModel::addVar(double, double, double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
      _fxn in simple-pRHAEs.o
架构x86_64的未定义符号: “GRBModel::addVar(双精度、双精度、双精度、字符、标准::\uuuu 1::基本字符串)”,引用自: _简单pRHAEs.o中的fxn

这是导致代码< > Dyn。Load 失败的相同的未定义的符号。

R正在期待C链接,但您已经提供C++链接。一个解决办法是

#include <iostream>

extern "C" void fxn() {
    std::cout << "Hello world" << std::endl;
}

我解决了这个问题,这与我如何将参数
-stdlib=libstdc++
提供给
R CMD SHLIB
有关
R CMD SHLIB
调用
clang++
两次,首先作为编译阶段构建一个对象文件(在我的例子中是
simple.o
),然后将该文件链接到一个共享对象(在我的例子中是
simple.so
R CMD SHLIB
仅将
-stdlib=libstdc++
参数传递给第二次调用,但我们需要它也为
clang++
的第一次调用提供参数。我们可以通过将
-stdlib=libstdc++
添加到
PKG\u cxflags
来实现这一点:

$ PKG_CXXFLAGS="-I/Library/gurobi562/mac64/include -stdlib=libstdc++" R CMD SHLIB \
  simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
  -stdlib=libstdc++ -lpthread -lm
clang++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG  \
  -I/usr/local/include   -I/Library/gurobi562/mac64/include -stdlib=libstdc++ \
  -fPIC  -mtune=core2 -g -O2  -c simple.cpp -o simple.o
clang++ -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup \
  -single_module -multiply_defined suppress -L/usr/local/lib -L/usr/local/lib \
  -o simple.so simple.o -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
  -stdlib=libstdc++ -lpthread -lm -F/Library/Frameworks/R.framework/.. \
  -framework R -Wl,-framework -Wl,CoreFoundation

现在,
dyn.load(“simple.so”)
在R中没有错误地工作(尽管正如@MartinMorgan和@JanvanderLaan所提到的,我需要使用
extern“C”
或从R调用函数的替代方法来公开我的函数)。

我怀疑R在加载
simple时找不到库。所以
。gurobi库的位置是否包含在
ld_library_path
(或Mac上的任何名称)中?库中有main也是很奇怪的,这可能会导致问题,您可能希望将
fxn
放在
外部“C”{
能够从R
echo$LD_LIBRARY_PATH调用它
产生正确的位置
:/LIBRARY/gurobi562/mac64/lib
,我还将它存储在
R_ldu LIBRARY_PATH
——不确定这是否重要。注释掉主函数并添加
extern“C”
dyn.load
问题没有帮助,尽管我会确保同时执行这两个操作,以便最终调用我的函数。
-stdlib=libstdc++
是Gurobi Optimizer 5所必需的。6@GregGlockner谢谢标准库最终成为了问题的核心——我已经将
-stdlib=libstdc++
传递给了链接器,但我还需要将
-stdlib=libstdc++
添加到
PKG\u cxflags
中,以便在编译阶段使用它。这不会在加载OP报告的库时导致错误。它只会由于名称被损坏,几乎无法调用
fxn
。谢谢,但不幸的是,添加
extern“C”
并不能解决
dyn.load
问题。
$ R --vanilla CMD SHLIB tmp.cpp && R --vanilla -e "dyn.load('tmp.so'); .C('fxn')"
clang++ -I/home/mtmorgan/bin/R-devel/include -DNDEBUG  -I/usr/local/include    -fpic  -ggdb -O0 -c tmp.cpp -o tmp.o
clang++ -shared -L/usr/local/lib -o tmp.so tmp.o -L/home/mtmorgan/bin/R-devel/lib -lR
> dyn.load('tmp.so'); .C('fxn')
Hello world
list()
$ PKG_CXXFLAGS="-I/Library/gurobi562/mac64/include -stdlib=libstdc++" R CMD SHLIB \
  simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
  -stdlib=libstdc++ -lpthread -lm
clang++ -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG  \
  -I/usr/local/include   -I/Library/gurobi562/mac64/include -stdlib=libstdc++ \
  -fPIC  -mtune=core2 -g -O2  -c simple.cpp -o simple.o
clang++ -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup \
  -single_module -multiply_defined suppress -L/usr/local/lib -L/usr/local/lib \
  -o simple.so simple.o -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
  -stdlib=libstdc++ -lpthread -lm -F/Library/Frameworks/R.framework/.. \
  -framework R -Wl,-framework -Wl,CoreFoundation