* Calling Nim from R
A super short introduction how to call Nim code from R using the =.C=
interface.
I'm not an R user normally, so I googled and used this post as a
reference:
https://www.r-bloggers.com/three-ways-to-call-cc-from-r/
** Writing our Nim procedure
Let's define a simple procedure, which we want Nim to do:
#+BEGIN_SRC nim
proc add5(x: int): int =
result = x + 5
#+END_SRC
How do we get this into a form to call it from R?
The =.C= interface expects loaded functions to receive arguments via
pointers and does not accept return values. So in C we need something
like:
#+BEGIN_SRC C
void add5(int* x){
*x = *x + 5;
}
#+END_SRC
Fortunately in Nim we don't have to deal with pointers manually. All
we need is to declare the argument as =var=:
#+BEGIN_SRC nim
proc add5(x: var int) =
x = x + 5
#+END_SRC
In addition leaving out the return type means we get a =void= return
type in C.
However, this function will be mangled when compiled to C, so we need
to tell the Nim compiler to leave it as is using the =exportc= pragma
like so:
#+BEGIN_SRC nim
proc add5(x: var int) {.exportc: "add5".} =
x = x + 5
#+END_SRC
Let's save this as =Rtest.nim= and we can compile it using:
#+BEGIN_SRC nim
nim c -d:release --noMain --app:lib Rtest.nim
#+END_SRC
After this we should have a =libRtest.so= in the current directory.
*** Check if =add5= shows up in C code
Just for curiosity, let's check whether disabling the name mangling
actually worked. Nowadays Nim stores the temporary files in
[[file:~/.cache/nim/][~/.cache/nim/<project_name>_<build_type>]]
so in our case:
[[file:~/.cache/nim/Rtestlib_r/][~/.cache/nim/Rtest_r/]]
If we open the [[file:~/.cache/nim/Rtest_r/Rtest.c][~/.cache/nim/Rtest_r/Rtest.c]] and search for =add5= we
should find a line like:
#+BEGIN_SRC C
N_NIMCALL(void, add5)(NI* x);
#+END_SRC
and further below:
#+BEGIN_SRC C
N_NIMCALL(void, add5)(NI* x) {
(*x) = (NI)((*x) + ((NI) 5));
}
#+END_SRC
which is just what we want, a =void= return type and an =NI= (Nim
integer) pointer.
** Call the lib from R
From here on all we need to do is call the code from R.
Let's start R:
#+BEGIN_SRC sh
R
#+END_SRC
and load the library:
#+BEGIN_SRC R
dyn.load("libRtest.so")
#+END_SRC
Now we can use the =.C= interface to call the =add5= function:
#+BEGIN_SRC R
.C("add5", x = as.integer(2))
#+END_SRC
should output =7=.
That's all there is to it!
* TODO how to call using =.Call= interface
Still todo.