8

foo は他の C 関数を.Call("foo", <args>)呼び出し、結果を計算して返します。結果は長さ 3 のリストになり、このリストに名前を付けたいと思います。この目的のために、foo は次のことを行います。

/* Construct result list from variables containing the results */
SEXP res = PROTECT(allocVector(VECSXP, 3)); /* list of length 3 */
SET_VECTOR_ELT(res, 0, ScalarReal(a)); /* numeric(1) */ 
SET_VECTOR_ELT(res, 1, somenumericvector); /* numeric(<some length>) */
SET_VECTOR_ELT(res, 2, ScalarInteger(i)); /* integer(1) */

/* Name components and return */
SEXP nms = PROTECT(allocVector(STRSXP, 3)); /* names as SEXP */
char *nms_ = CHAR(STRING_ELT(nms, 0)); /* pointer to names */
char *names[3] = {"result_numeric", "result_numeric_vector", "result_integer"};
for(i = 0; i < 3; i++) nms_[i] = names[i]; 
setAttrib(res, R_NamesSymbol, nms);
UNPROTECT(1); 
return res;

これは、長さ 3 の名前付きリストを作成する正しい方法ですか?

C 関数は確かに R に戻りますが、出力を R の変数に割り当てると、すぐにセグメンテーション違反が発生します。何が間違っている可能性がありますか? 「debug ステートメント」を配置できます (printf("...\n")上記の「return res;」の直前に簡単に配置できます。これらは正常に実行されます。R から呼び出された C コードをデバッグする便利な方法はありますか?

4

3 に答える 3

5

単純なバニラの方法を求めるので、 and を使用して C 文字列から R 文字ベクトルを作成する必要がありmkCharますSET_STRING_ELT

for(i = 0; i < 3; i++) SET_STRING_ELT(nms, i, mkChar(names[i]));  

現在、生の C 文字列を R オブジェクトとして使用しようとしていますが、これは機能しません。

再:デバッグ、PrintValueC コードで使用して R オブジェクトを出力できます。

とはいえ、プレーンなバニラが必要な特別な理由がない限り、Rcpp.

于 2015-05-16T18:24:00.273 に答える
3

@nrussell の良いアドバイスに従って、1 つのステートメントでの解決策 (読みやすくするために 4 行に分割)

R> cppFunction('List marius(double a, NumericVector b, int c) \
       { return List::create(Named("resnum")=a,\ 
                             Named("resvec")=b, \
                             Named("resint")=c); }')
R> marius(1.2, sqrt(3:5), 42L)
$resnum
[1] 1.2

$resvec
[1] 1.73205 2.00000 2.23607

$resint
[1] 42

R> 
于 2015-05-16T18:18:27.347 に答える