Rから使える関数をC言語で書くのはとても簡単だけど、文字列の渡し方についてななめ読みしてすぐわかる簡単な例がすぐ見つからなかったのでメモ。
hello.c
#include <stdio.h>
void hello(char** str)
{
if(str)
printf("Hello %s\n", *str);
}
コンパイルして hello.so
を作る(Mac OS/unix)。
% R CMD SHLIB hello.c
Rで使う:
dyn.load("hello.so")
hello <- function(val) {
.C("hello", as.character(val))
NULL
}
hello("world") # => Hello world
以上、とても簡単。
補足説明:
-
as.character()
は絶対に文字列しか渡さないというなら必要なけど、その場合うっかり文字列以外を渡すとヌル文字をみつけるまでメモリの彼方まで駆けだして死ぬ。 -
function(val)
の最後のNULL
は関数の戻り値。なんでもよい。 - C側の
if(str)
は NULL や list() など要素数がゼロのものを渡したときにstr=NULL
になることへの対策。
ベクトルを渡した場合は最初の要素だけが使われる:
hello(1:3) # => Hello 1
ベクトル対応
全部使いたい場合のベクトル化したバージョン。
hello.c
void vhello(char** str, int* n)
{
for(int i=0; i<*n; i++)
printf("Hello %s\n", str[i]);
}
vhello <- function(val) {
.C("vhello", as.character(val), length(val))
NULL
}
vhello(1:3) # => Hello 1
# Hello 2
# Hello 3
Keywords: Statical package R. Passing character strings from R to an extension written in C.