diff --git a/R-package/DESCRIPTION b/R-package/DESCRIPTION index 637e3435d..b1a91be17 100644 --- a/R-package/DESCRIPTION +++ b/R-package/DESCRIPTION @@ -1,7 +1,7 @@ Package: xgboost Type: Package Title: Extreme Gradient Boosting -Version: 0.6.4.3 +Version: 0.6.4.4 Date: 2017-01-04 Author: Tianqi Chen , Tong He , Michael Benesty , Vadim Khotilovich , diff --git a/R-package/NAMESPACE b/R-package/NAMESPACE index c3fac04e3..031bc7880 100644 --- a/R-package/NAMESPACE +++ b/R-package/NAMESPACE @@ -76,4 +76,4 @@ importFrom(utils,head) importFrom(utils,object.size) importFrom(utils,str) importFrom(utils,tail) -useDynLib(xgboost) +useDynLib(xgboost, .registration = TRUE) diff --git a/R-package/R/utils.R b/R-package/R/utils.R index f66f7cf99..ce93b8235 100644 --- a/R-package/R/utils.R +++ b/R-package/R/utils.R @@ -130,12 +130,11 @@ xgb.iter.update <- function(booster_handle, dtrain, iter, obj = NULL) { } if (is.null(obj)) { - .Call("XGBoosterUpdateOneIter_R", booster_handle, as.integer(iter), dtrain, - PACKAGE = "xgboost") + .Call(XGBoosterUpdateOneIter_R, booster_handle, as.integer(iter), dtrain) } else { pred <- predict(booster_handle, dtrain) gpair <- obj(pred, dtrain) - .Call("XGBoosterBoostOneIter_R", booster_handle, dtrain, gpair$grad, gpair$hess, PACKAGE = "xgboost") + .Call(XGBoosterBoostOneIter_R, booster_handle, dtrain, gpair$grad, gpair$hess) } return(TRUE) } @@ -153,8 +152,7 @@ xgb.iter.eval <- function(booster_handle, watchlist, iter, feval = NULL) { evnames <- names(watchlist) if (is.null(feval)) { - msg <- .Call("XGBoosterEvalOneIter_R", booster_handle, as.integer(iter), watchlist, - as.list(evnames), PACKAGE = "xgboost") + msg <- .Call(XGBoosterEvalOneIter_R, booster_handle, as.integer(iter), watchlist, as.list(evnames)) msg <- stri_split_regex(msg, '(\\s+|:|\\s+)')[[1]][-1] res <- as.numeric(msg[c(FALSE,TRUE)]) # even indices are the values names(res) <- msg[c(TRUE,FALSE)] # odds are the names diff --git a/R-package/R/xgb.Booster.R b/R-package/R/xgb.Booster.R index 2b2d2f241..94bd27028 100644 --- a/R-package/R/xgb.Booster.R +++ b/R-package/R/xgb.Booster.R @@ -6,15 +6,15 @@ xgb.Booster.handle <- function(params = list(), cachelist = list(), modelfile = stop("cachelist must be a list of xgb.DMatrix objects") } - handle <- .Call("XGBoosterCreate_R", cachelist, PACKAGE = "xgboost") + handle <- .Call(XGBoosterCreate_R, cachelist) if (!is.null(modelfile)) { if (typeof(modelfile) == "character") { - .Call("XGBoosterLoadModel_R", handle, modelfile[1], PACKAGE = "xgboost") + .Call(XGBoosterLoadModel_R, handle, modelfile[1]) } else if (typeof(modelfile) == "raw") { - .Call("XGBoosterLoadModelFromRaw_R", handle, modelfile, PACKAGE = "xgboost") + .Call(XGBoosterLoadModelFromRaw_R, handle, modelfile) } else if (inherits(modelfile, "xgb.Booster")) { bst <- xgb.Booster.complete(modelfile, saveraw = TRUE) - .Call("XGBoosterLoadModelFromRaw_R", handle, bst$raw, PACKAGE = "xgboost") + .Call(XGBoosterLoadModelFromRaw_R, handle, bst$raw) } else { stop("modelfile must be either character filename, or raw booster dump, or xgb.Booster object") } @@ -40,7 +40,7 @@ is.null.handle <- function(handle) { if (!identical(class(handle), "xgb.Booster.handle")) stop("argument type must be xgb.Booster.handle") - if (is.null(handle) || .Call("XGCheckNullPtr_R", handle, PACKAGE = "xgboost")) + if (is.null(handle) || .Call(XGCheckNullPtr_R, handle)) return(TRUE) return(FALSE) } @@ -237,8 +237,7 @@ predict.xgb.Booster <- function(object, newdata, missing = NA, option <- 0L + 1L * as.logical(outputmargin) + 2L * as.logical(predleaf) - ret <- .Call("XGBoosterPredict_R", object$handle, newdata, option[1], - as.integer(ntreelimit), PACKAGE = "xgboost") + ret <- .Call(XGBoosterPredict_R, object$handle, newdata, option[1], as.integer(ntreelimit)) if (length(ret) %% nrow(newdata) != 0) stop("prediction length ", length(ret)," is not multiple of nrows(newdata) ", nrow(newdata)) @@ -338,7 +337,7 @@ predict.xgb.Booster.handle <- function(object, ...) { xgb.attr <- function(object, name) { if (is.null(name) || nchar(as.character(name[1])) == 0) stop("invalid attribute name") handle <- xgb.get.handle(object) - .Call("XGBoosterGetAttr_R", handle, as.character(name[1]), PACKAGE = "xgboost") + .Call(XGBoosterGetAttr_R, handle, as.character(name[1])) } #' @rdname xgb.attr @@ -355,7 +354,7 @@ xgb.attr <- function(object, name) { value <- as.character(value[1]) } } - .Call("XGBoosterSetAttr_R", handle, as.character(name[1]), value, PACKAGE = "xgboost") + .Call(XGBoosterSetAttr_R, handle, as.character(name[1]), value) if (is(object, 'xgb.Booster') && !is.null(object$raw)) { object$raw <- xgb.save.raw(object$handle) } @@ -366,10 +365,10 @@ xgb.attr <- function(object, name) { #' @export xgb.attributes <- function(object) { handle <- xgb.get.handle(object) - attr_names <- .Call("XGBoosterGetAttrNames_R", handle, PACKAGE = "xgboost") + attr_names <- .Call(XGBoosterGetAttrNames_R, handle) if (is.null(attr_names)) return(NULL) res <- lapply(attr_names, function(x) { - .Call("XGBoosterGetAttr_R", handle, x, PACKAGE = "xgboost") + .Call(XGBoosterGetAttr_R, handle, x) }) names(res) <- attr_names res @@ -394,7 +393,7 @@ xgb.attributes <- function(object) { }) handle <- xgb.get.handle(object) for (i in seq_along(a)) { - .Call("XGBoosterSetAttr_R", handle, names(a[i]), a[[i]], PACKAGE = "xgboost") + .Call(XGBoosterSetAttr_R, handle, names(a[i]), a[[i]]) } if (is(object, 'xgb.Booster') && !is.null(object$raw)) { object$raw <- xgb.save.raw(object$handle) @@ -435,7 +434,7 @@ xgb.attributes <- function(object) { p <- lapply(p, function(x) as.character(x)[1]) handle <- xgb.get.handle(object) for (i in seq_along(p)) { - .Call("XGBoosterSetParam_R", handle, names(p[i]), p[[i]], PACKAGE = "xgboost") + .Call(XGBoosterSetParam_R, handle, names(p[i]), p[[i]]) } if (is(object, 'xgb.Booster') && !is.null(object$raw)) { object$raw <- xgb.save.raw(object$handle) diff --git a/R-package/R/xgb.DMatrix.R b/R-package/R/xgb.DMatrix.R index 72b973e0d..a6b04a6b6 100644 --- a/R-package/R/xgb.DMatrix.R +++ b/R-package/R/xgb.DMatrix.R @@ -26,15 +26,12 @@ xgb.DMatrix <- function(data, info = list(), missing = NA, silent = FALSE, ...) if (length(data) > 1) stop("'data' has class 'character' and length ", length(data), ".\n 'data' accepts either a numeric matrix or a single filename.") - handle <- .Call("XGDMatrixCreateFromFile_R", data, as.integer(silent), - PACKAGE = "xgboost") + handle <- .Call(XGDMatrixCreateFromFile_R, data, as.integer(silent)) } else if (is.matrix(data)) { - handle <- .Call("XGDMatrixCreateFromMat_R", data, missing, - PACKAGE = "xgboost") + handle <- .Call(XGDMatrixCreateFromMat_R, data, missing) cnames <- colnames(data) } else if (inherits(data, "dgCMatrix")) { - handle <- .Call("XGDMatrixCreateFromCSC_R", data@p, data@i, data@x, nrow(data), - PACKAGE = "xgboost") + handle <- .Call(XGDMatrixCreateFromCSC_R, data@p, data@i, data@x, nrow(data)) cnames <- colnames(data) } else { stop("xgb.DMatrix does not support construction from ", typeof(data)) @@ -100,8 +97,7 @@ xgb.get.DMatrix <- function(data, label = NULL, missing = NA, weight = NULL) { #' #' @export dim.xgb.DMatrix <- function(x) { - c(.Call("XGDMatrixNumRow_R", x, PACKAGE = "xgboost"), - .Call("XGDMatrixNumCol_R", x, PACKAGE = "xgboost")) + c(.Call(XGDMatrixNumRow_R, x), .Call(XGDMatrixNumCol_R, x)) } @@ -193,7 +189,7 @@ getinfo.xgb.DMatrix <- function(object, name, ...) { " 'label', 'weight', 'base_margin', 'nrow'") } if (name != "nrow"){ - ret <- .Call("XGDMatrixGetInfo_R", object, name, PACKAGE = "xgboost") + ret <- .Call(XGDMatrixGetInfo_R, object, name) } else { ret <- nrow(object) } @@ -240,29 +236,25 @@ setinfo.xgb.DMatrix <- function(object, name, info, ...) { if (name == "label") { if (length(info) != nrow(object)) stop("The length of labels must equal to the number of rows in the input data") - .Call("XGDMatrixSetInfo_R", object, name, as.numeric(info), - PACKAGE = "xgboost") + .Call(XGDMatrixSetInfo_R, object, name, as.numeric(info)) return(TRUE) } if (name == "weight") { if (length(info) != nrow(object)) stop("The length of weights must equal to the number of rows in the input data") - .Call("XGDMatrixSetInfo_R", object, name, as.numeric(info), - PACKAGE = "xgboost") + .Call(XGDMatrixSetInfo_R, object, name, as.numeric(info)) return(TRUE) } if (name == "base_margin") { # if (length(info)!=nrow(object)) # stop("The length of base margin must equal to the number of rows in the input data") - .Call("XGDMatrixSetInfo_R", object, name, as.numeric(info), - PACKAGE = "xgboost") + .Call(XGDMatrixSetInfo_R, object, name, as.numeric(info)) return(TRUE) } if (name == "group") { if (sum(info) != nrow(object)) stop("The sum of groups must equal to the number of rows in the input data") - .Call("XGDMatrixSetInfo_R", object, name, as.integer(info), - PACKAGE = "xgboost") + .Call(XGDMatrixSetInfo_R, object, name, as.integer(info)) return(TRUE) } stop("setinfo: unknown info name ", name) @@ -302,7 +294,7 @@ slice.xgb.DMatrix <- function(object, idxset, ...) { if (!inherits(object, "xgb.DMatrix")) { stop("object must be xgb.DMatrix") } - ret <- .Call("XGDMatrixSliceDMatrix_R", object, idxset, PACKAGE = "xgboost") + ret <- .Call(XGDMatrixSliceDMatrix_R, object, idxset) attr_list <- attributes(object) nr <- nrow(object) diff --git a/R-package/R/xgb.DMatrix.save.R b/R-package/R/xgb.DMatrix.save.R index 4ba8c498c..f25d31e5f 100644 --- a/R-package/R/xgb.DMatrix.save.R +++ b/R-package/R/xgb.DMatrix.save.R @@ -18,6 +18,6 @@ xgb.DMatrix.save <- function(dmatrix, fname) { if (!inherits(dmatrix, "xgb.DMatrix")) stop("dmatrix must be xgb.DMatrix") - .Call("XGDMatrixSaveBinary_R", dmatrix, fname[1], 0L, PACKAGE = "xgboost") + .Call(XGDMatrixSaveBinary_R, dmatrix, fname[1], 0L) return(TRUE) } diff --git a/R-package/R/xgb.dump.R b/R-package/R/xgb.dump.R index b9c857012..e57058330 100644 --- a/R-package/R/xgb.dump.R +++ b/R-package/R/xgb.dump.R @@ -51,8 +51,8 @@ xgb.dump <- function(model, fname = NULL, fmap = "", with_stats=FALSE, stop("fmap: argument must be a character string (when provided)") model <- xgb.Booster.complete(model) - model_dump <- .Call("XGBoosterDumpModel_R", model$handle, NVL(fmap, "")[1], as.integer(with_stats), - as.character(dump_format), PACKAGE = "xgboost") + model_dump <- .Call(XGBoosterDumpModel_R, model$handle, NVL(fmap, "")[1], as.integer(with_stats), + as.character(dump_format)) if (is.null(fname)) model_dump <- stri_replace_all_regex(model_dump, '\t', '') diff --git a/R-package/R/xgb.save.R b/R-package/R/xgb.save.R index 5d95ee664..426c70d14 100644 --- a/R-package/R/xgb.save.R +++ b/R-package/R/xgb.save.R @@ -37,6 +37,6 @@ xgb.save <- function(model, fname) { if (inherits(model, "xgb.DMatrix")) " Use xgb.DMatrix.save to save an xgb.DMatrix object." else "") } model <- xgb.Booster.complete(model, saveraw = FALSE) - .Call("XGBoosterSaveModel_R", model$handle, fname[1], PACKAGE = "xgboost") + .Call(XGBoosterSaveModel_R, model$handle, fname[1]) return(TRUE) } diff --git a/R-package/R/xgb.save.raw.R b/R-package/R/xgb.save.raw.R index 1743b67d7..ae27d04f0 100644 --- a/R-package/R/xgb.save.raw.R +++ b/R-package/R/xgb.save.raw.R @@ -19,5 +19,5 @@ #' @export xgb.save.raw <- function(model) { model <- xgb.get.handle(model) - .Call("XGBoosterModelToRaw_R", model, PACKAGE = "xgboost") + .Call(XGBoosterModelToRaw_R, model) } diff --git a/R-package/R/xgboost.R b/R-package/R/xgboost.R index 11a96c269..66c4c1bd2 100644 --- a/R-package/R/xgboost.R +++ b/R-package/R/xgboost.R @@ -105,5 +105,5 @@ NULL #' @importFrom graphics title #' #' @import methods -#' @useDynLib xgboost +#' @useDynLib xgboost, .registration = TRUE NULL diff --git a/R-package/src/Makevars.in b/R-package/src/Makevars.in index 53cd65563..26aa5386c 100644 --- a/R-package/src/Makevars.in +++ b/R-package/src/Makevars.in @@ -13,6 +13,6 @@ XGB_RFLAGS = -DXGBOOST_STRICT_R_MODE=1 -DDMLC_LOG_BEFORE_THROW=0\ PKG_CPPFLAGS= -I$(PKGROOT)/include -I$(PKGROOT)/dmlc-core/include -I$(PKGROOT)/rabit/include -I$(PKGROOT) $(XGB_RFLAGS) PKG_CXXFLAGS= @OPENMP_CXXFLAGS@ $(SHLIB_PTHREAD_FLAGS) PKG_LIBS = @OPENMP_CXXFLAGS@ $(SHLIB_PTHREAD_FLAGS) -OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o\ +OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o\ $(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o\ $(PKGROOT)/rabit/src/engine_empty.o $(PKGROOT)/rabit/src/c_api.o diff --git a/R-package/src/Makevars.win b/R-package/src/Makevars.win index ee2eb8982..953b5dc23 100644 --- a/R-package/src/Makevars.win +++ b/R-package/src/Makevars.win @@ -25,7 +25,7 @@ XGB_RFLAGS = -DXGBOOST_STRICT_R_MODE=1 -DDMLC_LOG_BEFORE_THROW=0\ PKG_CPPFLAGS= -I$(PKGROOT)/include -I$(PKGROOT)/dmlc-core/include -I$(PKGROOT)/rabit/include -I$(PKGROOT) $(XGB_RFLAGS) PKG_CXXFLAGS= $(SHLIB_OPENMP_CFLAGS) $(SHLIB_PTHREAD_FLAGS) PKG_LIBS = $(SHLIB_OPENMP_CFLAGS) $(SHLIB_PTHREAD_FLAGS) -OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o\ +OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o\ $(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o\ $(PKGROOT)/rabit/src/engine_empty.o $(PKGROOT)/rabit/src/c_api.o diff --git a/R-package/src/init.c b/R-package/src/init.c new file mode 100644 index 000000000..c19e618b9 --- /dev/null +++ b/R-package/src/init.c @@ -0,0 +1,74 @@ +/* Copyright (c) 2015 by Contributors + * + * This file was initially generated using the following R command: + * tools::package_native_routine_registration_skeleton('.', con = 'src/init.c', character_only = F) + * and edited to conform to xgboost C linter requirements. For details, see + * https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Registering-native-routines + */ +#include +#include +#include +#include + +/* FIXME: +Check these declarations against the C/Fortran source code. +*/ + +/* .Call calls */ +extern SEXP XGBoosterBoostOneIter_R(SEXP, SEXP, SEXP, SEXP); +extern SEXP XGBoosterCreate_R(SEXP); +extern SEXP XGBoosterDumpModel_R(SEXP, SEXP, SEXP, SEXP); +extern SEXP XGBoosterEvalOneIter_R(SEXP, SEXP, SEXP, SEXP); +extern SEXP XGBoosterGetAttr_R(SEXP, SEXP); +extern SEXP XGBoosterGetAttrNames_R(SEXP); +extern SEXP XGBoosterLoadModel_R(SEXP, SEXP); +extern SEXP XGBoosterLoadModelFromRaw_R(SEXP, SEXP); +extern SEXP XGBoosterModelToRaw_R(SEXP); +extern SEXP XGBoosterPredict_R(SEXP, SEXP, SEXP, SEXP); +extern SEXP XGBoosterSaveModel_R(SEXP, SEXP); +extern SEXP XGBoosterSetAttr_R(SEXP, SEXP, SEXP); +extern SEXP XGBoosterSetParam_R(SEXP, SEXP, SEXP); +extern SEXP XGBoosterUpdateOneIter_R(SEXP, SEXP, SEXP); +extern SEXP XGCheckNullPtr_R(SEXP); +extern SEXP XGDMatrixCreateFromCSC_R(SEXP, SEXP, SEXP, SEXP); +extern SEXP XGDMatrixCreateFromFile_R(SEXP, SEXP); +extern SEXP XGDMatrixCreateFromMat_R(SEXP, SEXP); +extern SEXP XGDMatrixGetInfo_R(SEXP, SEXP); +extern SEXP XGDMatrixNumCol_R(SEXP); +extern SEXP XGDMatrixNumRow_R(SEXP); +extern SEXP XGDMatrixSaveBinary_R(SEXP, SEXP, SEXP); +extern SEXP XGDMatrixSetInfo_R(SEXP, SEXP, SEXP); +extern SEXP XGDMatrixSliceDMatrix_R(SEXP, SEXP); + +static const R_CallMethodDef CallEntries[] = { + {"XGBoosterBoostOneIter_R", (DL_FUNC) &XGBoosterBoostOneIter_R, 4}, + {"XGBoosterCreate_R", (DL_FUNC) &XGBoosterCreate_R, 1}, + {"XGBoosterDumpModel_R", (DL_FUNC) &XGBoosterDumpModel_R, 4}, + {"XGBoosterEvalOneIter_R", (DL_FUNC) &XGBoosterEvalOneIter_R, 4}, + {"XGBoosterGetAttr_R", (DL_FUNC) &XGBoosterGetAttr_R, 2}, + {"XGBoosterGetAttrNames_R", (DL_FUNC) &XGBoosterGetAttrNames_R, 1}, + {"XGBoosterLoadModel_R", (DL_FUNC) &XGBoosterLoadModel_R, 2}, + {"XGBoosterLoadModelFromRaw_R", (DL_FUNC) &XGBoosterLoadModelFromRaw_R, 2}, + {"XGBoosterModelToRaw_R", (DL_FUNC) &XGBoosterModelToRaw_R, 1}, + {"XGBoosterPredict_R", (DL_FUNC) &XGBoosterPredict_R, 4}, + {"XGBoosterSaveModel_R", (DL_FUNC) &XGBoosterSaveModel_R, 2}, + {"XGBoosterSetAttr_R", (DL_FUNC) &XGBoosterSetAttr_R, 3}, + {"XGBoosterSetParam_R", (DL_FUNC) &XGBoosterSetParam_R, 3}, + {"XGBoosterUpdateOneIter_R", (DL_FUNC) &XGBoosterUpdateOneIter_R, 3}, + {"XGCheckNullPtr_R", (DL_FUNC) &XGCheckNullPtr_R, 1}, + {"XGDMatrixCreateFromCSC_R", (DL_FUNC) &XGDMatrixCreateFromCSC_R, 4}, + {"XGDMatrixCreateFromFile_R", (DL_FUNC) &XGDMatrixCreateFromFile_R, 2}, + {"XGDMatrixCreateFromMat_R", (DL_FUNC) &XGDMatrixCreateFromMat_R, 2}, + {"XGDMatrixGetInfo_R", (DL_FUNC) &XGDMatrixGetInfo_R, 2}, + {"XGDMatrixNumCol_R", (DL_FUNC) &XGDMatrixNumCol_R, 1}, + {"XGDMatrixNumRow_R", (DL_FUNC) &XGDMatrixNumRow_R, 1}, + {"XGDMatrixSaveBinary_R", (DL_FUNC) &XGDMatrixSaveBinary_R, 3}, + {"XGDMatrixSetInfo_R", (DL_FUNC) &XGDMatrixSetInfo_R, 3}, + {"XGDMatrixSliceDMatrix_R", (DL_FUNC) &XGDMatrixSliceDMatrix_R, 2}, + {NULL, NULL, 0} +}; + +void R_init_xgboost(DllInfo *dll) { + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); +} diff --git a/doc/how_to/contribute.md b/doc/how_to/contribute.md index bad0455ad..5a5b58b8b 100644 --- a/doc/how_to/contribute.md +++ b/doc/how_to/contribute.md @@ -158,3 +158,7 @@ Some additional consideration is needed when the core library version changes. E.g., after the core changes from 0.6 to 0.7, the R package development version would become 0.7.0.1, working towards a 0.7.1 CRAN release. The 0.7.0 would not be released to CRAN, unless it would require almost no additional development. +### Registering native routines in R +According to [R extension manual](https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Registering-native-routines), +it is good practice to register native routines and to disable symbol search. When any changes or additions are made to the +C++ interface of the R package, please make corresponding changes in ```src/init.c``` as well. diff --git a/include/xgboost/c_api.h b/include/xgboost/c_api.h index f4792ad5a..decdcd0bf 100644 --- a/include/xgboost/c_api.h +++ b/include/xgboost/c_api.h @@ -2,11 +2,13 @@ * Copyright (c) 2015 by Contributors * \file c_api.h * \author Tianqi Chen - * \brief C API of XGBoost, used to interfacing with other languages. + * \brief C API of XGBoost, used for interfacing to other languages. */ #ifndef XGBOOST_C_API_H_ #define XGBOOST_C_API_H_ +#include + #ifdef __cplusplus #define XGB_EXTERN_C extern "C" #endif @@ -62,7 +64,7 @@ typedef struct { /*! * \brief Callback to set the data to handle, * \param handle The handle to the callback. - * \param batch The data content to be setted. + * \param batch The data content to be set. */ XGB_EXTERN_C typedef int XGBCallbackSetData( DataHolderHandle handle, XGBoostBatchCSR batch);