我发现我们可以从内存地址构建/重建外部指针,请参阅这个例子,我从数据表对象中获取指针并重建它:
# devtools::install_github("randy3k/xptr")
iris_dt <- data.table::as.data.table(iris)
ptr1 <- attr(iris_dt, ".internal.selfref")
ptr1
#> <pointer: 0x13c00d4e0>
typeof(ptr1)
#> [1] "externalptr"
address <- xptr::xptr_address(ptr1)
address
#> [1] "0x13c00d4e0"
ptr2 <- xptr::new_xptr(address)
identical(ptr1, ptr2)
#> [1] TRUE
显然xptr::new_xptr("0x13c00d4e0")
在会话之间是不稳定的,我知道上面不是分配内存,而是定义绑定,这对我的用例来说很好。
我想对环境做同样的事情:
e <- new.env()
e
#> <environment: 0x10b5bf038>
env("0x10b5bf038") # I want this "env" function
#> <environment: 0x10b5bf038>
我怀疑base R可以做到这一点,所以我对打包选项和C魔法持开放态度。
不需要阅读X/Y注解
对于the {constructive} package,我需要这个,比如说我想探索asNamespace("stats")$.__NAMESPACE__.$DLLs
对象,它打印的方式不是很有帮助:
asNamespace("stats")$.__NAMESPACE__.$DLLs
#> $stats
#> DLL name: stats
#> Filename: /opt/R/4.2.1-arm64/Resources/library/stats/libs/stats.so
#> Dynamic lookup: FALSE
dput()
通常是丑陋和脆弱的,另外这里的代码不是语法的,所以我不能确定对象被准确地描述了。
dput(asNamespace("stats")$.__NAMESPACE__.$DLLs)
#> list(stats = structure(list(name = "stats", path = "/opt/R/4.2.1-arm64/Resources/library/stats/libs/stats.so",
#> dynamicLookup = FALSE, handle = <pointer: 0x2011ce960>, info = <pointer: 0x6000021f00c0>), class = "DLLInfo"))
str()
稍好一些,但在一般情况下并不理想。
str(asNamespace("stats")$.__NAMESPACE__.$DLLs)
#> List of 1
#> $ stats:List of 5
#> ..$ name : chr "stats"
#> ..$ path : chr "/opt/R/4.2.1-arm64/Resources/library/stats/libs/stats.so"
#> ..$ dynamicLookup: logi FALSE
#> ..$ handle :Class 'DLLHandle' <externalptr>
#> ..$ info :Class 'DLLInfoReference' <externalptr>
#> ..- attr(*, "class")= chr "DLLInfo"
{constructive}保证了它输出的代码可以重现对象,现在它对包含指针的对象起作用。
constructive::construct(asNamespace("stats")$.__NAMESPACE__.$DLLs)
#> list(
#> stats = list(
#> name = "stats",
#> path = "/opt/R/4.2.1-arm64/Resources/library/stats/libs/stats.so",
#> dynamicLookup = FALSE,
#> handle = constructive::external_pointer("0x2051d6960") |>
#> structure(class = "DLLHandle"),
#> info = constructive::external_pointer("0x600002970de0") |>
#> structure(class = "DLLInfoReference")
#> ) |>
#> structure(class = "DLLInfo")
#> )
我在包中有其他方法来处理环境,例如从列表中构建等效环境等......但我想集成一个仅使用内存地址的替代方案,因为它可以更好地打印,并且对于某些用例来说已经足够了。
1条答案
按热度按时间ujv3wf0j1#
如果存在安全和可移植的版本,你需要做更多的工作来使它安全和可移植。注意整数类型
uintptr_t
和对应的宏格式说明符SCNxPTR
是optional in C99。请参阅WRE中的“编写可移植的包”下的建议。你想问的问题:
objectFromAddress
之前,垃圾回收器释放了该地址的内存,会发生什么情况?SEXPREC
的地址,会发生什么?在实践中,您(维护者)需要从R* 中保证 * 在这两种情况下都不会调用此函数。