Debugging (line by line) of Rcpp-generated DLL under Windows

后端 未结 1 1701
清歌不尽
清歌不尽 2020-12-08 21:06

Recently I\'ve been experimenting with Rcpp (inline) to generate DLLs that perform various tasks on supplied R inputs. I\'d like to be able to debug the code in thes

相关标签:
1条回答
  • 2020-12-08 21:28

    I am a little stunned by the obsession some Rcpp users have with the inline package and its cxxfunction(). Yes, it is indeed very helpful and it has surely has driven adoption of Rcpp further as it makes quick experimentation so much easier. Yes, it allowed us to use 700+ unit tests in the sources. Yes, I use it all the time to demonstrate examples here, on the rcpp-devel list or even live in presentations.

    But does that mean we should use it for each and every task? Does it mean that it does not have "costs" such as randomized filenames in a temporary directory etc pp? Romain and I argued otherwise in our documentation.

    Lastly, debugging of dynamically loaded R modules is difficult as it stands. There is an entire section in the (mandatory) Writing R Extensions about it, and Doug Bates once or twice posted a tutorial about how to do this via ESS and Emacs (though I always forget where he posted it; once was IIRC on the rcpp-devel list).

    Edit 2012-Jul-07:

    Here is your step by step:

    • (Preamble: I've used gcc and g++ for many years, and even when I add -g I don't always turn -O2 into -O0. I am really not sure you need that, but as you ask for it...)

    • Set your environment variable CXXFLAGS to "-g -O0 -Wall". There numerous ways to do it, some are platform-dependent (eg Windows control panel) and therefore less universal and interesting. I use ~/.R/Makevars on Windows and Unix. You could use that, or you could override R's system-wide $RHOME/etc/Makeconf or you could use Makeconf.site or ... See the full docs---but as I said, ~/.R/Makevars is my preferred way as it does NOT interfere with compilation outside of R.

    • Now every compilation R does via R CMD SHLIB, R CMD COMPILE, R CMD INSTALL, ... will use. So it no longer matters you use inline or a local package. Continuing with inline...

    • For the rest, we mostly follow 'Section 4.4.1 Finding entry points in dynamically loaded code' of "Writing R Extensions":

    • Start another R session with R -d gdb.

    • Compile your code. For

    fun <- cxxfunction(signature(), plugin="Rcpp", verbose=TRUE, body='
       int theAnswer = 42;
       return wrap(theAnswer);
    ')
    

    I get

    [...]
    Compilation argument:
     /usr/lib/R/bin/R CMD SHLIB file11673f928501.cpp 2> file11673f928501.cpp.err.txt 
     ccache g++-4.6 -I/usr/share/R/include -DNDEBUG   -I"/usr/local/lib/R/site- library/Rcpp/include"   -fpic  -g -O0 -Wall -c file11673f928501.cpp -o file11673f928501.o
    g++-4.6 -shared -o file11673f928501.so file11673f928501.o -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib/R/lib -lR
    
    • Invoke eg tempdir() to see the temporary directory, cd to this temporary directory used above and dyn.load() the file built above:
     dyn.load("file11673f928501.so")
    
    • Now suspend R by sending a break signal (in Emacs, a simple choice from a drop-down).

    • In gdb, set a breakpoint. The single assignment above became line 32 for me, so

    break file11673f928501.cpp 32
    cont
    
    • Back in R, call the function:

      fun()

    • Presto, in the debugger at the break point we wanted:

    R> fun()
    
    Breakpoint 1, file11673f928501 () at file11673f928501.cpp:32
    32      int theAnswer = 42;
    (gdb) 
    
    • Now it is "just" up to you to work gdb to its magic

    Now, as I said in my first attempt, all this would be easier (in my eyes) via a simple package which Rcpp.package.skeleton() can write for you as you don't have to deal with randomized directories and filenames. But each to their own...

    0 讨论(0)
提交回复
热议问题