R dyn.load & quot; Символ не найден & quot; ошибка, даже несмотря на то, что код на C ++ работает нормально

У меня есть простая программа на C ++, которую я могу успешно построить, используя clang++ на моем Mac (Mavericks), но это не удается при сборке с R CMD SHLIB и загружен dyn.load в Р.

Это код C ++ (хранится в simple.cpp), который использует оптимизатор Gurobi:

#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;
}

Я могу успешно скомпилировать и запустить этот код, используя clang++, ссылаясь на библиотеки Gurobi:

$ clang++ simple.cpp -I/Library/gurobi562/mac64/include \
-L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 -stdlib=libstdc++ \
-lpthread -lm
$ ./a.out
Hello world

Я могу успешно скомпилировать с 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::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >), которая должна быть предоставлена ​​одной из библиотек Gurobi, на которую я ссылаюсь.

Из предыдущих постов я узнал, что эти ошибки «Symbol not found» часто возникают из-за того, что они не связывают правильные библиотеки, но я смог успешно скомпилировать и запустить simple.cpp и я передаю те же варианты ссылок на R CMD SHLIB,

Ниже приводится содержание моего ~/.R/Makevars файл:

CC=clang
CXX=clang++

редактировать Я думаю, что проблема может быть связана с опцией -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

Это тот же неопределенный символ, который вызывает dyn.load терпеть неудачу.

1

Решение

Я решил эту проблему, которая оказалась связана с тем, как я приводил аргумент -stdlib=libstdc++ в R CMD SHLIB, R CMD SHLIB Запускает clang++ дважды, сначала как этап компиляции для создания объектного файла (simple.o в моем случае), а затем связать этот файл в общий объект (simple.so в моем случае). R CMD SHLIB проходил только -stdlib=libstdc++ аргумент для второго вызова, но нам нужно также предоставить аргумент для первого вызова clang++, Мы можем сделать это, добавив -stdlib=libstdc++ в PKG_CXXFLAGS:

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

2

Другие решения

R ожидает связи с C, но вы предоставили связь с C ++. Одним из решений является

#include <iostream>

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

с

$ 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()
0

По вопросам рекламы [email protected]