text 如何使用`.C`接口从R调用Nim代码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了text 如何使用`.C`接口从R调用Nim代码相关的知识,希望对你有一定的参考价值。

* 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.

以上是关于text 如何使用`.C`接口从R调用Nim代码的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Nim 的主块返回退出代码?

如何使用“外部函数接口”从 Go 调用 C

如何从 Nim 的导入失败中恢复?

如何从本机 C(++) DLL 调用 .NET (C#) 代码?

如何从 vbscript 调用 c# dll

如何使用Qt和C ++的“接口类”来传递两个线程