为了说明,让我们考虑一个具体的例子,任何人都应该能够运行…
下面的代码是一个非常简单的cxxfunction,只需将输入向量加倍.但是请注意,还有一个额外的变量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放在位置tempdir()中,这对我来说是当前的
C:/Users/TimP/AppData/Local/Temp/RtmpXuxtpa/file7e61645c.dll
> f0(c(-7,0.7,77)) $out1 [1] -14.0 1.4 154.0
但是我们当然也可以使用.Call命令直接通过名称来调用DLL:
> .Call("file7e61645c",c(-7,77)) $out1 [1] -14.0 1.4 154.0
所以我已经达到了直接用R输入(这里是向量c(-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”)替换,并将相关文件复制到更永久的位置.
提前感谢你的帮助:)