从 R 获取 C 变量?
Getting C variables from R?
这是我的问题。我想知道我的 R 会话中有多少个打开的 RODBC 连接。也许这个问题与 Show all open RODBC connections 有关。
问题是,如果我不将连接分配给变量,我将无法使用它,即我使用 odbcConnect()
而不是 channel<-odbcConnect()
,因为没有环境变量创建。
我查看了 RODBC 包的 C 代码,似乎有一个变量 nChannels
,其中包含打开连接数的 int
。我可以从 R 中调用这个变量,甚至可以使用 C 函数吗?
R 环境如何在这里发挥作用?还是完全无关?任何解释将不胜感激,因为我在这方面非常新。如果我处理这个问题的逻辑也有误,请指教。
如果用户提交他们自己的代码,解决方案很简单:提供您的 自己的 函数 odbcConnect
,它会在内部记录调用,然后分派到 {RODBC}包裹。也就是说,不要让用户直接访问 RODBC 包。
只要您为用户提供设置(即用户永远不会调用 library(RODBC)
,也不会调用 RODBC::odbcConnect
),这就有效。
但如果不是这种情况,即如果用户直接与 RODBC 包交互,则您需要更进一步:您需要自己修改 RODBC 包。您可以通过在运行时修补函数来完成此操作,但这是 相当先进的 (而且很脆弱;如果 RODBC 升级并更改其实现,它就会中断)。这是一个最小的例子:
log_connect_expr = quote(assign('.odbc_connections', .GlobalEnv$.odbc_connections + 1, .GlobalEnv))
log_close_expr = quote(assign('.odbc_connections', .GlobalEnv$.odbc_connections - 1, .GlobalEnv))
# Inject expression into a function body at a given position, counting either
# from the beginning or from the end (if `pos` < 0).
insert_in_body = function (body, expr, pos) {
body = as.list(body)
if (pos < 0) pos = length(body) + pos + 1
all_indices = seq_along(body)
before_indices = all_indices < pos
after_indices = all_indices >= pos
as.call(c(body[before_indices], expr, body[after_indices]))
}
# Insert log calls into function bodies, after any error checking.
local({
odbcDriverConnect = RODBC::odbcDriverConnect
body(odbcDriverConnect) = insert_in_body(body(odbcDriverConnect), log_connect_expr, -1)
odbcClose = RODBC::odbcClose
body(odbcClose) = insert_in_body(body(odbcClose), log_close_expr, 4)
assignInNamespace('odbcDriverConnect', odbcDriverConnect, getNamespace('RODBC'))
assignInNamespace('odbcClose', odbcClose, getNamespace('RODBC'))
})
# Initialize counter
.GlobalEnv$.odbc_connections = 0
或者,只需下载 RODBC 源代码,修改它,构建包并在本地安装。所有这些解决方案都是 hacky,但总比在 RODBC 的 C 内部结构中翻找要好。
读取内部 RODBC 连接状态不实用。首先,变量 nChannels
似乎不是打开连接数的准确计数;它更像是一个上限,关闭连接不会减少计数器。
但即使它是准确的,你也无法读取它,因为该变量已声明 static
,因此不会导出。
这是我的问题。我想知道我的 R 会话中有多少个打开的 RODBC 连接。也许这个问题与 Show all open RODBC connections 有关。
问题是,如果我不将连接分配给变量,我将无法使用它,即我使用 odbcConnect()
而不是 channel<-odbcConnect()
,因为没有环境变量创建。
我查看了 RODBC 包的 C 代码,似乎有一个变量 nChannels
,其中包含打开连接数的 int
。我可以从 R 中调用这个变量,甚至可以使用 C 函数吗?
R 环境如何在这里发挥作用?还是完全无关?任何解释将不胜感激,因为我在这方面非常新。如果我处理这个问题的逻辑也有误,请指教。
如果用户提交他们自己的代码,解决方案很简单:提供您的 自己的 函数 odbcConnect
,它会在内部记录调用,然后分派到 {RODBC}包裹。也就是说,不要让用户直接访问 RODBC 包。
只要您为用户提供设置(即用户永远不会调用 library(RODBC)
,也不会调用 RODBC::odbcConnect
),这就有效。
但如果不是这种情况,即如果用户直接与 RODBC 包交互,则您需要更进一步:您需要自己修改 RODBC 包。您可以通过在运行时修补函数来完成此操作,但这是 相当先进的 (而且很脆弱;如果 RODBC 升级并更改其实现,它就会中断)。这是一个最小的例子:
log_connect_expr = quote(assign('.odbc_connections', .GlobalEnv$.odbc_connections + 1, .GlobalEnv))
log_close_expr = quote(assign('.odbc_connections', .GlobalEnv$.odbc_connections - 1, .GlobalEnv))
# Inject expression into a function body at a given position, counting either
# from the beginning or from the end (if `pos` < 0).
insert_in_body = function (body, expr, pos) {
body = as.list(body)
if (pos < 0) pos = length(body) + pos + 1
all_indices = seq_along(body)
before_indices = all_indices < pos
after_indices = all_indices >= pos
as.call(c(body[before_indices], expr, body[after_indices]))
}
# Insert log calls into function bodies, after any error checking.
local({
odbcDriverConnect = RODBC::odbcDriverConnect
body(odbcDriverConnect) = insert_in_body(body(odbcDriverConnect), log_connect_expr, -1)
odbcClose = RODBC::odbcClose
body(odbcClose) = insert_in_body(body(odbcClose), log_close_expr, 4)
assignInNamespace('odbcDriverConnect', odbcDriverConnect, getNamespace('RODBC'))
assignInNamespace('odbcClose', odbcClose, getNamespace('RODBC'))
})
# Initialize counter
.GlobalEnv$.odbc_connections = 0
或者,只需下载 RODBC 源代码,修改它,构建包并在本地安装。所有这些解决方案都是 hacky,但总比在 RODBC 的 C 内部结构中翻找要好。
读取内部 RODBC 连接状态不实用。首先,变量 nChannels
似乎不是打开连接数的准确计数;它更像是一个上限,关闭连接不会减少计数器。
但即使它是准确的,你也无法读取它,因为该变量已声明 static
,因此不会导出。