簡體   English   中英

如何從 C 中調用 R 的 order 函數(通過 R_orderVector())?

[英]How to call R's order function from within C (via R_orderVector())?

在 R 包內調用的 C 函數中,我需要對一些數字進行排序。 為了與 R 的功能保持一致,我想調用 R 使用的排序算法/函數,即 R_orderVector()。 我恰好在調用 R_orderVector() 時遇到分段錯誤。 下面是重現分段錯誤的最小工作示例(“最小工作包”的文件)。 我究竟做錯了什么?

### DESCRIPTION ################################################################

Package: foo
Version: 0.0-1
Encoding: UTF-8
Title: Sorting from C via R's R_orderVector()
Description: See title
Authors@R: c(person(given = "Foo", family = "Bar", role = c("aut", "cre"), email = "foo@bar.com"))
Author: Foo Bar [aut, cre]
Maintainer: Foo Bar <foo@bar.com>
Depends: R (>= 3.0.0)
Imports:
Suggests:
Enhances:
License: GPL-2 | GPL-3
NeedsCompilation: yes
Repository: CRAN
Date/Publication: 2014-03-25 15:26:50


### NAMESPACE ##################################################################

useDynLib(foo, .registration = TRUE)
export("myRsort")


### ./R/mySort.R ###############################################################

myRsort <- function(x) {
    stopifnot(is.numeric(x), length(x) <= 64)
    myRsort_ <- NULL # to avoid "myRsort_: no visible binding for global variable 'myRsort_'"
    .Call("myRsort_", x)
}


### ./man/myRsort.Rd ###########################################################

\name{myRsort}
\alias{myRsort}
\title{Using R's Sorting Algorithm from C}
\description{
  R's sorting algorithm is called from C.
}
\usage{
myRsort(x)
}
\arguments{
  \item{x}{vector}
}
\value{
  vector
}
\author{Marius Hofert}
\examples{
set.seed(271)
x <- runif(10)
myRsort(x)
}
\keyword{utilities}


### ./src/init.c ###############################################################

#include <R.h>
#include <Rinternals.h>
#include <R_ext/Rdynload.h>

#include "myRsort.h"


static const R_CallMethodDef callMethods[] = {
    {"myRsort_", (DL_FUNC) &myRsort_, 1},
    {NULL, NULL, 0}
};

void R_init_foo(DllInfo *dll)
{
    R_useDynamicSymbols(dll, FALSE);
    R_registerRoutines(dll, NULL, callMethods, NULL, NULL); /* s. WRE (2015, Section 5.4) */
}


### ./src/myRsort.c ############################################################

#include "myRsort.h"

void myRsort_aux(double *x, int n, double *res)
{
    int *ind; /* pointer to vector of indices as required for order (permutation of 0:(n-1)) */
    ind = (int *) R_alloc(n, sizeof(int));

    SEXP xsexp = PROTECT(allocVector(REALSXP, n)); /* turn x into SEXP */
    double *xsexp_ = REAL(xsexp); /* pointer */

    R_orderVector(ind, n, xsexp, TRUE, TRUE); /* nalast (use same default as order()); decreasing=TRUE */
    /* the last line generates a seg-fault */

    int i;
    for(i=0; i<n; i++) res[i] = x[ind[i]];
}

SEXP myRsort_(SEXP x)
{
    double *x_ = REAL(x); /* pointer to n-vector */
    int n = LENGTH(x); /* length n */
    int maxlen = 64; /* vector can be at most of length 64 here */

    SEXP res = PROTECT(allocVector(REALSXP, maxlen)); /* result */
    double *res_ = REAL(res); /* pointer to the (sorted) result */
    myRsort_aux(x_, n, res_);

    UNPROTECT(1);
    return res;
}


### ./src/myRsort.h ############################################################

#ifndef myRsort_H
#define myRsort_H

#include <R.h>
#include <Rinternals.h>
#include <Rmath.h>

void myRsort_aux(double *x, int n, double *res);
SEXP myRsort_(SEXP x);

#endif

好像你:

  • 忘記了UNPROTECT
  • 沒有復制myRsort_aux的值。
  • 沒有正確使用R_orderVector函數。

這是一個工作示例,可以是Rcpp::sourceCpp ed:

#include <Rcpp.h>

void myRsort_aux(double *x, int n, double *res)
{
  int *ind = (int *) R_alloc(n, sizeof(int));
  
  SEXP xsexp = PROTECT(Rf_allocVector(REALSXP, n));
  // you forgot to copy the values?
  for(int i = 0; i < n; ++i)
    REAL(xsexp)[i] = x[i];
  // a call as in https://github.com/wch/r-source/blob/7dcdfc2d2d0ce3ce6fe84aa1cf0d27b5cbc833fc/src/main/sort.c#L1096
  R_orderVector(ind, n, Rf_lang1(xsexp), TRUE, TRUE);
  
  for(int i = 0; i < n; i++) 
    res[i] = x[ind[i]];
  
  UNPROTECT(1); // seems like you forgot this
}

// [[Rcpp::export(rng = false)]]
SEXP myRsort_(SEXP x)
{
  double *x_ = REAL(x);
  int n = LENGTH(x); 
  int maxlen = 64; 
  
  SEXP res = PROTECT(Rf_allocVector(REALSXP, maxlen)); 
  double *res_ = REAL(res); 
  myRsort_aux(x_, n, res_);
  
  UNPROTECT(1);
  return res;
}

/*** R
set.seed(1)
to_be_sorted <- rnorm(10)
head(myRsort_(to_be_sorted), 10)
#R> [1]  1.5952808  0.7383247  0.5757814  0.4874291  0.3295078  0.1836433 -0.3053884 -0.6264538 -0.8204684 -0.8356286
*/

在這種情況下,您可能只使用R_rsort

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM