我有一個第三方C庫用於編寫R擴展。我需要在庫中創建一些結構(並初始化它們),我需要將它們作爲S4對象的一部分進行維護(將這些結構視爲定義計算狀態,摧毀它們將會摧毀所有剩餘的計算和所有已經計算的結果)。 我想創建一個S4對象來保持指針這些結構爲void*
指針,但它不完全清楚如何這樣做,什麼是槽的類型?S4指針指向C的對象struct
回答
正如@hrbrmstr指出的那樣,你可以使用externalptr
型保持這樣的對象「活着」,這是在寫R附加的this section觸及,但我看不出有任何理由,你爲什麼會需要存儲任何東西如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
創建的指針是通常足夠使用Rcpp::XPtr<SomeClass>
工作,因爲default finalizer只是調用舉行對象delete
。但是,由於您正在處理C API,因此我們必須提供(默認)模板參數Rcpp::PreserveStorage
,更重要的是提供適當的終結器(本例中爲free_CStruct
),以便XPtr
不會在通過malloc
分配的內存上調用delete
,當相應的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
存儲在RUpdateCStruct(ptr, x)
將修改存儲在CStruct
數據,SummarizeCStruct(ptr)
將打印摘要等rm(ptr); gc()
將刪除ptr
對象並迫使垃圾收集器來運行,從而調用free_CStruct(ptr)
和對事物的C側銷燬對象以及
您提到了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 Gallery的帖子! –
- 1. 指向Struct的指針的指針
- 2. 指向對象的指針指向C++對象範圍之外
- 3. Struct對象名稱在C指針
- 4. 指向對象開始的指針(C++)
- 5. C++矢量對象與指向對象的指針的向量
- 6. 無效指針指向對象指針
- 7. 使用矢量指針指向對象的指針C++
- 8. 指向圓的指針的數組struct
- 9. 設置指向對象的指針,讓對象指向對方
- 10. 指向const對象的指針自動轉換爲指向對象的指針
- 11. 指向「value struct x」的指針
- 12. 刪除指針向量中的指針指向的對象
- 13. C++ push_back對象並獲取指向對象的指針
- 14. 如何創建指向指向struct的指針數組的指針?
- 15. C++轉換:有指向對象成員的指針,計算指向對象的指針
- 16. 指向指向頭痛的struct的指針。 。
- 17. C++對象指針
- 18. 指向C中的指針的指針
- 19. 指向現有對象的指針?
- 20. 指向對象的指針混亂
- 21. 指向對象類型的指針
- 22. boost :: gil指向bgr8_view_t對象的指針
- 23. 獲取雙指針指向的對象
- 24. 解引用指向對象的指針
- 25. C++強制指針指向指向基指向指針的指針
- 26. 在C中指向struct和malloc的指針?
- 27. 如何更改struct中指針指向的值c?
- 28. 在使用ctypes的傳遞指向struct指針C函數
- 29. C - 指向struct的指針數組,語法
- 30. C++ - 指向模板數組的指針struct
https://stat.ethz.ch/R-manual/R-devel/library/methods/html/BasicClasses.html:'externalptr' – hrbrmstr