私はRエクステンションを書くために使用しているサードパーティのCライブラリを持っています。私はS4オブジェクトの一部としてそれらを維持する必要があるライブラリ内で定義されたいくつかの構造体を作成する必要があります(これらの構造体を計算の状態に定義すると考えると、それらを破壊するのは残りのすべてを破棄することです計算とそのすべての結果が既に計算されている)。 ポインタを保持するS4オブジェクトを作成しようと考えていますが、これらの構造体はvoid*
ポインタとしていますが、どのようにするのかはまったく分かりません。S4構造体へのポインタを持つオブジェクト
答えて
としては、私はあなたが保存する必要がありますなぜ何らかの理由が表示されませんが、あなたが、執筆R拡張機能のthis sectionに触れされ、「生きている」ようなオブジェクトを維持するためにexternalptr
タイプを使用することができ、@hrbrmstrによって指摘しました何でもvoid*
。少しC++を使用することに問題がなければ、Rcpp class XPtr
は、EXTPTRSXP
を管理するのに必要なかなりの量の定型文を削除することができます。例として、以下の簡単な例を想定して、あなたのサードパーティのライブラリのAPIを表します
#include <Rcpp.h>
#include <stdlib.h>
typedef struct {
unsigned int count;
double total;
} CStruct;
CStruct* init_CStruct() {
return (CStruct*)::malloc(sizeof(CStruct));
}
void free_CStruct(CStruct* ptr) {
::free(ptr);
::printf("free_CStruct called.\n");
}
typedef Rcpp::XPtr<CStruct, Rcpp::PreserveStorage, free_CStruct> xptr_t;
new
を介して作成ポインタを操作するときdefault finalizerは、単に保持された物体のdelete
を呼び出すためには、Rcpp::XPtr<SomeClass>
を使用することが一般的に十分です。しかし、C APIを扱っているので、XPtr
がmalloc
によって割り当てられたメモリ上でdelete
を呼び出さないように、(デフォルトの)テンプレートパラメータRcpp::PreserveStorage
、さらに重要なのは、適切なファイナライザ(この例ではfree_CStruct
)対応するRオブジェクトがガベージコレクションされたときなどに発生します。
例を続けると、あなたはCStruct
と対話するには、次の関数を記述前提としています。この時点で
// [[Rcpp::export]]
xptr_t MakeCStruct() {
CStruct* ptr = init_CStruct();
ptr->count = 0;
ptr->total = 0;
return xptr_t(ptr, true);
}
// [[Rcpp::export]]
void UpdateCStruct(xptr_t ptr, SEXP x) {
if (TYPEOF(x) == REALSXP) {
R_xlen_t i = 0, sz = XLENGTH(x);
for (; i < sz; i++) {
if (!ISNA(REAL(x)[i])) {
ptr->count++;
ptr->total += REAL(x)[i];
}
}
return;
}
if (TYPEOF(x) == INTSXP) {
R_xlen_t i = 0, sz = XLENGTH(x);
for (; i < sz; i++) {
if (!ISNA(INTEGER(x)[i])) {
ptr->count++;
ptr->total += INTEGER(x)[i];
}
}
return;
}
Rf_warning("Invalid SEXPTYPE.\n");
}
// [[Rcpp::export]]
void SummarizeCStruct(xptr_t ptr) {
::printf(
"count: %d\ntotal: %f\naverage: %f\n",
ptr->count, ptr->total,
ptr->count > 0 ? ptr->total/ptr->count : 0
);
}
// [[Rcpp::export]]
int GetCStructCount(xptr_t ptr) {
return ptr->count;
}
// [[Rcpp::export]]
double GetCStructTotal(xptr_t ptr) {
return ptr->total;
}
// [[Rcpp::export]]
void ResetCStruct(xptr_t ptr) {
ptr->count = 0;
ptr->total = 0.0;
}
を、あなたはRからCStructs
の取り扱いを開始するのに十分行っている:
-
を
ptr <- MakeCStruct()
はCStruct
を初期化し、externalptr
として保存します。UpdateCStruct(ptr, x)
CStruct
に格納されたデータを修正する、SummarizeCStruct(ptr)
サマリーを印刷する、等rm(ptr); gc()
したがってfree_CStruct(ptr)
を呼び出して物事のC側のオブジェクトを破壊する、ptr
オブジェクトを削除して実行するガベージコレクタを強制します同様に
これらの関数をすべて1つの場所に格納するためのオプションの1つであるS4クラスの使用について説明しました。ここでは一つの可能性があります:
setClass(
"CStruct",
slots = c(
ptr = "externalptr",
update = "function",
summarize = "function",
get_count = "function",
get_total = "function",
reset = "function"
)
)
setMethod(
"initialize",
"CStruct",
function(.Object) {
[email protected] <- MakeCStruct()
[email protected] <- function(x) {
UpdateCStruct([email protected], x)
}
[email protected] <- function() {
SummarizeCStruct([email protected])
}
[email protected]_count <- function() {
GetCStructCount([email protected])
}
[email protected]_total <- function() {
GetCStructTotal([email protected])
}
[email protected] <- function() {
ResetCStruct([email protected])
}
.Object
}
)
その後、我々はこのようなCStruct
秒で動作することができます。もちろん
ptr <- new("CStruct")
[email protected]()
# count: 0
# total: 0.000000
# average: 0.000000
set.seed(123)
[email protected](rnorm(100))
[email protected]()
# count: 100
# total: 9.040591
# average: 0.090406
[email protected](rnorm(100))
[email protected]()
# count: 200
# total: -1.714089
# average: -0.008570
[email protected]()
[email protected]()
# count: 0
# total: 0.000000
# average: 0.000000
rm(ptr); gc()
# free_CStruct called.
# used (Mb) gc trigger (Mb) max used (Mb)
# Ncells 484713 25.9 940480 50.3 601634 32.2
# Vcells 934299 7.2 1650153 12.6 1308457 10.0
、別のオプションは、どの多かれ少なかれ、Rcpp Modulesを使用することですR側のクラス定義の定型句を処理します(ただし、S4クラスではなく参照クラスを使用します)。
優れた答え。おそらくRcppギャラリーの投稿にもなりますか? –
- 1. 構造体へのポインタを持つ構造体:ベスト・アプローチ
- 2. 構造体にポインタを持つ構造体へのポインタの配列
- 3. C++構造体オブジェクト型エラーへのポインタ
- 4. C構造体へのポインタを持つ構造体 - 値にアクセスする
- 5. 構造体へのポインタへのポインタ
- 6. 構造体へのポインタへのポインタ
- 7. 構造体メンバへのポインタ
- 8. 構造体へのポインタ
- 9. ポインタ構造体を持つSWIG関数
- 10. 自己へのポインタを持つC構造体
- 11. 構造体パラメータへのポインタを持つC#ネイティブコールバック
- 12. 構造体のポインタへのポインタ
- 13. 構造体のポインタからの構造体の値へのアクセス
- 14. 構造体の配列内の構造体へのポインタ
- 15. 異なる構造体内の構造体へのポインタ。 C
- 16. C#:構造体内の構造体へのポインタ
- 17. C:構造体内の構造体要素へのポインタ
- 18. C++構造体のポインタを持つ構造体を初期化するには、
- 19. C構造体、構造体へのポインタ、適切な初期化
- 20. 構造体へのポインタを返す
- 21. 構造体のメンバ変数への(通常の)ポインタを構造体全体へのポインタに変換する
- 22. 構造体定義のポインタを持つ列挙体
- 23. 構造体へのポインタの配列へのポインタを返す
- 24. Cの構造体へのポインタのrealloc()
- 25. C++ - 構造体のクラスへのポインタ?
- 26. 構造体へのvoidポインタのキャスト
- 27. C別の構造体へのポインタ
- 28. 構造体の配列へのポインタ
- 29. 構造体へのポインタのC配列
- 30. マイクロコントローラ上のアクセスレジスタへの構造体ポインタ?
https://stat.ethz.ch/R-manual/R-devel/library/methods/html/BasicClasses.html: 'externalptr' – hrbrmstr