[英]Undefined reference when building R package using Rcpp with an external C++ library
我正在嘗試創建一個R包供我自己使用,即使用Rcpp,其C ++代碼包括Levmar庫。 我在Windows上工作。
例如,當我使用CMake構建C ++代碼並使用Visual Studio運行它時,C ++代碼就可以正常工作。 但是,當我將此代碼放入R包並嘗試構建它時,出現以下錯誤:
levmar_example_r.o:levmar_example_r.cpp :(。text + 0x281):對'dlevmar_der'的未定義引用
(dlevmar_der在levmar.h中聲明,該文件包含在我的R包中,請參見下文)
我已經閱讀了很多關於如何構建A R封裝,如外部庫,以便帖子這個還是這個 ,但它並沒有幫助我解決我的問題。
我的包裹的結構:
bin/
|- levmar.lib
inst/
|- include/
|- levmar.h
man/
R/
src/
|- Makevars
|- Makevars.win
|- levmar_example_r.cpp
|- RcppExports.cpp
src-i386/
DESCRIPTION
NAMESPACE
Makevars / Makevars.win的內容
PKG_LIBS = -L../bin -llevmar
PKG_CPPFLAGS = -I../inst/include
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;
}
我還嘗試將levmar庫的所有標頭放在inst / include文件夾中,並將所有.c文件放在src / levmar文件夾中,然后刪除
PKG_LIBS = -L../bin -llevmar
在Makevars / Makevars.win中添加
-I src/levmar
到PKG_CPPFLAGS,但也沒有解決。
您對我應該做什么有任何想法嗎?
如果我不夠清楚,請隨時詢問精度
SODD讓我更好。 我已經構建了一個非常粗糙的軟件包,可以編譯levmar代碼,並從中創建一個初始的R軟件包: https : //github.com/rstub/levmaR 。 要點:
src
子目錄中的源文件不會自動編譯。 一個人必須以某種方式添加它們,例如
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)
默認情況下,levmar嘗試構建單精度和雙精度函數,並嘗試使用LAPACK。 R的默認版本僅包括雙精度LAPACK和BLAS。 我禁用了單精度構建。
levmar庫實際上是純C語言。因此,我懷疑您的問題是由VC和gcc之間的不同C ++ ABI引起的。 VC和gcc之間最有可能在靜態庫的布局方面存在其他不兼容性。
現在唯一可用的函數是test_levmar()
。 在Linux和Windows(通過Appveyor和rhub)上進行了測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.