It is possible to write R extensions in Nim. Here is a rather useless example:
type sexptype = cuint
const realsxp = 14
type sexp {.importc: "SEXP", header: "<Rinternals.h>".} = object
proc protect(s: sexp): sexp
{.importc: "PROTECT", header: "<Rinternals.h>".}
proc unprotect(s: cint)
{.importc: "UNPROTECT", header: "<Rinternals.h>".}
proc allocVector(t: sexptype, n: cint): sexp
{.importc: "allocVector", header: "<Rinternals.h>".}
proc asReal(a: sexp): cdouble
{.importc: "asReal", header: "<Rinternals.h>".}
proc real(a: sexp): ptr cdouble
{.importc: "REAL", header: "<Rinternals.h>".}
proc add(a, b: sexp): sexp {.exportc, dynlib.} =
result = protect(allocVector(realsxp, 1))
real(result)[] = asReal(a)+asReal(b)
unprotect(1)
On my Windows machine (with 64 bit R, 64 bit Nim 0.16.0 and whatever gcc comes
with RBuildTools) I compile it like this:
`nim c -t:-m64 -l:-m64 -t:-I"C:/PROGRA~1/R/R-32~1.0/include" -t:-DNDEBUG
-t:-I"d:/RCompile/r-compiling/local/local320/include" -t:-mtune=core2
-l:-Ld:/RCompile/r-compiling/local/local320/lib/x64
-l:-Ld:/RCompile/r-compiling/local/local320/lib
-l:-LC:/PROGRA~1/R/R-32~1.0/bin/x64 -l:-lR --app:lib usewithR2.nim`
Then it can be used from R like this:
dyn.load("usewithR2.dll")
print(.Call("add", 1.5, 3.2))
And it prints [1] 4.7. So far so good. However, it can't be distributed easily.
CRAN probably wouldn't accept a package that requires a working Nim compiler to
be installed. Is it possible to generate a platform-independent (as in
"Windows, Linux and OS X", not as in "every possible AVR microcontroller") C
file that does not require anything related to Nim and can be compiled with R
CMD SHLIB? I had no success with options like `--os:standalone`, but maybe I
didn't use it correctly. I would appreciate your help.