Back
Splus to C Interfacing
Splus Guides and Release Notes:
Unix/Linux
Windows
Updated for use with Splus 6.0, and R 1.5.1
--------------------------------------------------------
STEP (1): Write a C program. Here is an example:
% cat add.c
#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#define PI 3.14159
#define NMAX 100
void add(double *x, double *y, long *nn, double *out) {
long n = *nn;
int i;
for(i=0;i<n;i++) *(out+i) = *(x+i) + *(y+i);
/* for (i=0;i<n;i++) out[i] = x[i] + y[i]; */
}
Note 1: All arguments must be pointers.
Note 2: Any variable that is integer in S must be long in C [Nb., in
gcc on linux, int's and long's are the same, so this matters
less].
Note 3: It is recommended that the return type of the C function be
"void" but it doesn't seem to matter much.
----------------------------------------------------------
STEP (2): Compile it using the appropriate command:
For Splus:
==========
linux% Splus CHAPTER add.c # This will APPEND onto any existing
# makefile. Only need to do it once
# per function that you are creating
# This also creates a local .Data
# directory to store variables in. If
# you do not want this, say "rm -R .Data"
# before going on...
linux% Splus make # do this every time you change the .c
# file...
For R:
======
linux% R CMD SHLIB add.c # do this every time you change the .c
# file...
----------------------------------------------------------
STEP (3): Link it into Splus/R using the appropriate command:
For Splus:
==========
> dyn.open("S.so") # can be skipped if you keep the local .Data
# directory from Splus CHAPTER add.c
For R:
======
> dyn.load("add.so") # This is the default name but it can be changed.
----------------------------------------------------------
STEP (4): Write an S function as follows:
[ this is called a "wrapper function"; it just
smooths the rough edges between Splus/R and C ]
add.fun = function(x,y){
n = length(x)
out = as.double(rep(0,n))
z = .C("add", x=as.double(x), y=as.double(y), n=as.integer(n),
out=as.double(out))
z
}
Note 4: To return something with a name, you must set aside a variable
with that name. For example, the variable out is used for that
purpose. Make sure out is the right length.
Note 5: As we will see below, .C returns a list whose elements are all
the arguments passed to the C function, modified in whatever
way the C function modified them.
----------------------------------------------------------
STEP (5): Try it:
x = c(1,2,3)
y = c(4,5,6)
add.fun(x,y)
Splus output:
=============
$"x":
[1] 1 2 3
$"y":
[1] 4 5 6
$"n":
[1] 3
$out:
[1] 5 7 9
R output:
=========
$x
[1] 1 2 3
$y
[1] 4 5 6
&n
[1] 3
$out
[1] 5 7 9
----------------------------------------------------------
STEP (6): If you want to modify the source code you have to
(a) unlink the old version from Splus or R:
Splus: > dyn.close("add.so")
R: > dyn.unload("add.so")
(b) change the source code
(c) recompile and relink using the instructions above
----------------------------------------------------------
MORE HELP BY TYPING
Splus: > help(dyn.open)
R: > help(dyn.load)
AND FOLLOWING THE "RELATED TOPICS" FROM EITHER HELP PAGE.
----------------------------------------------------------