[英]Undefined reference when building R package using Rcpp with an external C++ library
I'm trying to create a R package for my own use, that is using Rcpp and whose C++ code include the Levmar library. 我正在尝试创建一个R包供我自己使用,即使用Rcpp,其C ++代码包括Levmar库。 I'm working on Windows.
我在Windows上工作。
The C++ code works fine when I build it using CMake for example and run it with Visual Studio. 例如,当我使用CMake构建C ++代码并使用Visual Studio运行它时,C ++代码就可以正常工作。 But when I put this code in my R package and try to build it, I get the following error :
但是,当我将此代码放入R包并尝试构建它时,出现以下错误:
levmar_example_r.o:levmar_example_r.cpp:(.text+0x281): undefined reference to `dlevmar_der'
levmar_example_r.o:levmar_example_r.cpp :(。text + 0x281):对'dlevmar_der'的未定义引用
(dlevmar_der is declared in levmar.h which is included in my R package, see below) (dlevmar_der在levmar.h中声明,该文件包含在我的R包中,请参见下文)
I have already read quite a lot of SO posts on how to build a R package with external libraries like this or this but it didn't help me to solve my problem. 我已经阅读了很多关于如何构建A R封装,如外部库,以便帖子这个还是这个 ,但它并没有帮助我解决我的问题。
The structure of my package : 我的包裹的结构:
bin/
|- levmar.lib
inst/
|- include/
|- levmar.h
man/
R/
src/
|- Makevars
|- Makevars.win
|- levmar_example_r.cpp
|- RcppExports.cpp
src-i386/
DESCRIPTION
NAMESPACE
Content of Makevars/Makevars.win Makevars / Makevars.win的内容
PKG_LIBS = -L../bin -llevmar
PKG_CPPFLAGS = -I../inst/include
The C++ code (levmar_example_r.cpp) C ++代码(levmar_example_r.cpp)
#include <iostream>
#include <levmar.h>
#include <math.h>
#include <Rcpp.h>
void fun(double *p, double *x, int m, int n, void *data_){
double a = p[0];
double b = p[1];
double *data = (double *) data_;
for(int i = 0; i < n; i++){
x[i] = log(a*data[i]+b);
}
}
void jacFun(double *p, double *jac, int m, int n, void *data_){
double a = p[0];
double b = p[1];
double *data = (double *) data_;
int k, l;
for(l=k=0; l < n; l++){
jac[k++] = data[l]/(a*data[l]+b);
jac[k++] = 1/(a*data[l]+b);
}
}
// [[Rcpp::export]]
void test_levmar(){
int m = 2; // # of parameters
int n = 40; // # of observations
double a = 1.0;
double b = 2.0;
double data[] = {0.119047619047619, 0.238095238095238, 0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143,
0.119047619047619 ,0.238095238095238, 0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714 ,1.07142857142857, 1.42857142857143 ,
0.119047619047619, 0.238095238095238, 0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143,
0.119047619047619, 0.238095238095238, 0.357142857142857, 0.476190476190476 ,0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143,
0.119047619047619, 0.238095238095238 ,0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143};
double popti[2];
popti[0] = a; popti[1] = b;
double x[40];
fun(popti, x, m, n, (void *) data);
// algorithm parameters
double opts[LM_OPTS_SZ], info[LM_INFO_SZ];
opts[0]=LM_INIT_MU;
// stopping thresholds for
opts[1]=1E-10; // ||J^T e||_inf
opts[2]=1E-10; // ||Dp||_2
opts[3]=1E-10; // ||e||_2
opts[4]= LM_DIFF_DELTA; // finite difference if used
double p[2];
p[0] = 3.0; p[1] = 1.0;
dlevmar_der(fun,jacFun,p,x,m,n,100,opts,info,NULL,NULL,(void *) data);
std::cout << "Optimum found:" << std::scientific << std::setprecision(8)<< "\t"<< p[0]<< "\t" << p[1]<< std::endl;
}
I have also tried to put all headers of the levmar library in the inst/include folder and all the .c files in a src/levmar folder and consequently remove 我还尝试将levmar库的所有标头放在inst / include文件夹中,并将所有.c文件放在src / levmar文件夹中,然后删除
PKG_LIBS = -L../bin -llevmar
in Makevars/Makevars.win and add 在Makevars / Makevars.win中添加
-I src/levmar
to the PKG_CPPFLAGS but it didn't work out either. 到PKG_CPPFLAGS,但也没有解决。
Do you have any idea on what I should do ? 您对我应该做什么有任何想法吗?
Don't hesitate to ask for precisions if I wasn't clear enough 如果我不够清楚,请随时询问精度
SODD got the better of me. SODD让我更好。 I have build a very rough package that compiles the levmar code and creates an initial R package from it: https://github.com/rstub/levmaR .
我已经构建了一个非常粗糙的软件包,可以编译levmar代码,并从中创建一个初始的R软件包: https : //github.com/rstub/levmaR 。 Important points:
要点:
Source files in sub-directories of src
are not automatically compiled. src
子目录中的源文件不会自动编译。 One has to add them somehow, eg 一个人必须以某种方式添加它们,例如
CXX_STD = CXX11 PKG_LIBS=-L. -llevmar $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) PKG_CPPFLAGS=-I./levmar/ -DSTRICT_R_HEADERS all: $(SHLIB) $(SHLIB): liblevmar.a LIBOBJS = levmar/lm.o levmar/Axb.o levmar/misc.o levmar/lmlec.o levmar/lmbc.o \\ levmar/lmblec.o levmar/lmbleic.o liblevmar.a: $(LIBOBJS) $(AR) rcs liblevmar.a $(LIBOBJS)
By default levmar tries to build single- and double-precision functions and tries to use LAPACK. 默认情况下,levmar尝试构建单精度和双精度函数,并尝试使用LAPACK。 Default builds of R only include double-precision LAPACK and BLAS.
R的默认版本仅包括双精度LAPACK和BLAS。 I disabled the single precision build.
我禁用了单精度构建。
The levmar library is actually pure C. So my suspicion that your problems where caused by the different C++ ABIs between VC and gcc is probably not correct. levmar库实际上是纯C语言。因此,我怀疑您的问题是由VC和gcc之间的不同C ++ ABI引起的。 Most likely there is some other incompatibility between VC and gcc concerning the layout of static libraries.
VC和gcc之间最有可能在静态库的布局方面存在其他不兼容性。
Right now the only available function is your test_levmar()
. 现在唯一可用的函数是
test_levmar()
。 Tested on Linux and Windows (via Appveyor and rhub). 在Linux和Windows(通过Appveyor和rhub)上进行了测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.