最近我一直在尝试使用 Rcpp(内联)来生成 DLL,这些 DLL 在提供的 R 输入上执行各种任务。给定一组特定的 R 输入,我希望能够逐行调试这些 DLL 中的代码。(我在 Windows 下工作。)
为了说明,让我们考虑一个任何人都应该能够运行的特定示例......
下面的代码是一个非常简单的 cxx 函数,它只是将输入向量加倍。但是请注意,还有一个额外的变量myvar
可以更改几次值但不影响输出 - 已添加此变量,以便我们能够看到调试过程何时正确运行。
library(inline)
library(Rcpp)
f0 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='
Rcpp::NumericVector xa(a);
int myvar = 19;
int na = xa.size();
myvar = 27;
Rcpp::NumericVector out1(na);
for(int i=0; i < na; i++) {
out1[i] = 2*xa[i];
myvar++;
}
myvar = 101;
return(Rcpp::List::create( _["out1"] = out1));
')
在我们运行上面之后,输入命令
getLoadedDLLs()
在 R 会话中显示 DLL 列表。列出的最后一个应该是上述过程创建的 DLL - 它有一个随机的临时名称,在我的例子中是
file7e61645c
“文件名”列显示 cxxfunction 已将此 DLL 放在 locationtempdir()
中,对我来说目前是
C:/Users/TimP/AppData/Local/Temp/RtmpXuxtpa/file7e61645c.dll
现在,调用 DLL 的明显方法是 via f0
,如下
> f0(c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
但我们当然也可以使用以下.Call
命令直接按名称调用 DLL:
> .Call("file7e61645c",c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
所以我已经达到了直接使用 R 输入(这里是 vector c(-7,0.7,77)
)调用独立 DLL 并让它正确地将答案返回给 R的地步。
不过,我真正需要的是一个用于逐行调试的工具(我猜是使用 gdb),它可以让我观察myvar
设置为 19、27、28、29、30 和最后 101 的值代码进展。上面的示例是故意设置的,因此调用 DLL 不会告诉我们有关 myvar 的任何信息。
澄清一下,这里的“获胜条件”是能够观察 myvar 的变化(看到值 myvar=19 将是第一步!)而不向代码主体添加任何其他内容。这显然可能需要更改代码的编译方式(是否有调试模式设置可以打开?),或者调用 R 的方式 - 但我不知道从哪里开始。如上所述,所有这些都是基于 Windows 的。
最后说明:在我的实验中,我实际上对 cxxfunction 的副本进行了一些小修改,以便输出 DLL - 以及其中的代码 - 接收用户定义的名称并位于用户定义的目录中,而不是临时名称和位置。但这并不影响问题的本质。我提到这一点只是为了强调如果有人轻推我,更改编译设置应该相当容易:)
为了完整起见,在上面的原始 cxxfunction 调用中设置 verbose=TRUE 显示编译参数为以下形式:
C:/R/R-2.13.2/bin/i386/R CMD SHLIB file7e61645c.cpp 2> file7e61645c.cpp.err.txt
g++ -I"C:/R/R-213~1.2/include" -I"C:/R/R-2.13.2/library/Rcpp/include" -O2 -Wall -c file7e61645c.cpp -o file7e61645c.o
g++ -shared -s -static-libgcc -o file7e61645c.dll tmp.def file7e61645c.o C:/R/R-2.13.2/library/Rcpp/lib/i386/libRcpp.a -LC:/R/R-213~1.2/bin/i386 -lR
我的改编版本有一个与上面相同的编译参数,除了字符串“file7e61645c”被用户选择的名称(例如“testdll”)替换并且相关文件复制到更永久的位置。
在此先感谢您的帮助:)