Introducing {callme} - a package for easily(?) compiling and loading C code into #RStats
I use this idea when testing small snippets of C code as part of developing bigger ideas & packages.
Using this approach, it is also possible to quickly link to other C libraries. In the example below, I link to the 'zstd' library and request the library version number as a string.
This is a nice(?) wrapper around "R CMD COMPILE/SHLIB"
Example The following example compiles a code snippet into a C library and then executes the function from R using SCall() . The function name in C is add_ , which means that this is the first argument to .call() i.e. .Call(*add_", wee) The function name could be almost any valid C function name, but I prefer to use an underscore suffix to indicate that this a C function meant to be called from R. library(callme) code <- " #include#include SEXP add_(SEXP vall_, SEXP val2_) { return ScalarReal(asReal(vall_) + asReal(val2_)); } callme(code) .Call("add_", 1, 2.5) n
Linking against an installed library The following code snippet asks for the version of the zstd library which is (already) installed on the computer, and return it as a character string. We need to tell R when compiling the code: to look in the /opt/homebrew/include directory for zstd.h . « to look for the actual zstd library in /opt/homebrew/lib . « tolink to the zstd library ( -lzstd ) code < r( #include#include#include "zstd.h" SEXP version_() { return mkString(ZSTD_versionString()); ¥ ) callme(code, cpp_flags = "-I/opt/homebrew/include”, ld_flags = “-L/opt/homebrew/lib -lzstd") .Call("version_")
[> library(callme) R PRSI W + #include + + SEXP add_(SEXP vall_, SEXP valz)) { + return ScalarReal(asReal(vall ) + asReal(val2_)); L] o > callme(code) clang -arch armé4 -I"/Library/Frameworks/R. framework/Resources/include” -DNDEBUG -I/opt/R/arm64/i nclude -fPIC -falign-functions=64 -Wall -g -02 -c callme-16da937995196.c -0 callme-16da9379951 9.0 using C compiler: ‘Apple clang version 14.0.3 (clang-1403.0.22.14.1)° using SDK: ‘MacOSX13.3.sdk’ clang -arch armé4 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_mo dule -multiply_defined suppress -L/Library/Frameworks/R.framework/Resources/1ib -L/opt/R/arm64/lib -0 callme-16da937995196.50 callme-16da937995196.0 ~F/Library/Frameworks/R. framework/. . -framework R -WL,-framework -WL,CoreFoundation > .Call("add_", 1, 2.5) 1] 3.5 > ](https://cdn.fosstodon.org/media_attachments/files/110/740/491/318/612/573/original/4cdd4a5cd3c9fe83.png)
Developer note: Nearly every single one of my projects has started with these 3 thoughts:
That'd be cool.
It can't be that hard.
It should only take me a few hours to do.
Then I spend the next month* riding the Dunning Kruger wave - realising there's so much I don't know that I don't know! - and thinking my past self a fool for ever thinking this was possible.
Now that this pkg is actually in a state where it can do something useful, I can quickly realize some ideas for rendering. From idea to proof-of-concept render was ~15 minutes.
This is a ggplot object rendered into isometric layers.
It's just a shear + foreshortening transformation applied to the geometry, with points further offset in the y axis.