R ne peut appeler que des fonctions écrites en C, C++ ou Fortran. Cette fiche présente les bases de ces appels.
Contraintes sur les programmes
- R ne peut appeler que des fonctions C ou Fortran ne retournant pas de valeur. Les fonctions C doivent donc être de type
void
et les routines Fortran, des subroutines. Les résultats doivent être mis dans des arguments sauf si on utiliseCall
voir la fiche Appeler du C, du C++ ou du Fortran depuis R: notions avancées) ouRcpp
.
Exemple en Fortran: (fichier ma_sommeF.f
)
subroutine ma_sommeF(a, b, res)
integer a,b
double precision res
res = (a+b)/2.0
end
- Les arguments des sous-programmes C doivent tous être des pointeurs. La fonction C suivante n’est donc pas directement utilisable sous R:
/* Ancienne routine non utilisable sous R */
double sommeC(int a, int b)
{
return((double)(a+b)/2.0);
}
Il faut l’adapter pour la rendre appelable par R de la manière suivante: (fichier ma_sommeC.c
)
/* Nouvelle version adaptee a R */
void ma_sommeC(int *a, int *b, double *res)
{
*res=(double)(*a+*b)/2.0;
}
Si on ne dispose pas du code source de la fonction à appeler, il faut écrire une fonction “d’enrobage”.
Exemple:
void sommeC_enrobee(int *a, int *b, double *res)
{
*res=sommeC(*a,*b);
}
- En Fortran, les majuscules et minuscules ne sont pas distinguées: donnez un nom en minuscule au nom des sous-programmes Fortran.
Conventions sur les types des arguments
Correspondances:
R | C | Fortran |
---|---|---|
integer | int* | integer |
numeric | double* | double precision |
- or - | float* | real |
complex | Rcomplex* | double complex |
logical | int* | integer |
character | char** | [see below] |
list | SEXP* | not allowed |
order | SEXP | not allowed |
Pour en savoir plus (passage des valeurs manquantes, des caractères accentués, des complexes), voir la partie Interface functions .C and .Fortran dans l’aide en ligne de R.
Pour les listes, voir le paragraphe Passer une liste en argument d’un programme C dans la fiche Appeler du C, du C++ ou du Fortran depuis R: notions avancées.
Compilation/édition de liens
Les sous-programmes C et Fortran sont compilés et “linkés” dans une librairie partagée (shared library), par la commande R CMD SHLIB
Exemple:
R CMD SHLIB -o ma_somme.so ma_sommeC.c ma_sommeF.f
Les fichiers C ma_sommeC.c
et Fortran ma_sommeF.f
sont compilés et linkés dans la librairie de nom ma_somme.so
.
En l’absence d’option -o nom-de-librairie.so
, le nom de la librairie a pour préfixe le nom de son premier argument et pour suffixe .so
(ce suffixe peut être différent sur certaines installations, en particulier sous Windows).
Exemple:
R CMD SHLIB ma_sommeC.c ma_sommeF.f
Le fichier ma_sommeC.so
est créé.
La compilation et l’édition de liens sont faites en utilisant les compilateurs et les options qui ont servi à l’installation de R sur la machine courante. On peut définir ses propres options dans un fichier Makevars
: voir le paragraphe Définir les options de compilation via un Makevars dans la fiche Appeler du C, du C++ ou du Fortran depuis R: notions avancées.
Chargement des programmes dans la session R
La commande R pour charger dans la session une librairie partagée est: dyn.load()
.
Exemple: chargement de la librairie ma_somme.so
du répertoire courant.
dyn.load("ma_somme.so")
Attention: À chaque modification du source C ou Fortran, il faut refaire la commande Unix R CMD SHLIB
et la commande R dyn.load()
.
Appel des programmes dans la session R
L’appel aux programmes C et Fortran depuis R se fait par les fonctions .C()
et .Fortran()
.
Le premier argument de ces commandes est le nom de la fonction à appeller, les arguments suivants sont les arguments de la fonction C ou Fortran.
Exemples: (fichier ma_somme.R
). Un appel à la fonction ma_sommeC:
out <- .C("ma_sommeC", as.integer(1), as.integer(4), as.double(0))
et un appel à la fonction ma_sommeF
:
out <- .Fortran("ma_sommef", as.integer(1), as.integer(4), as.double(0))
Remarques:
- Nous avons explicitement converti tous les arguments dans le type R correspondant, afin de prévenir d’éventuelles erreurs de typage.
- En Fortran, la différence majuscules/minuscules est ignorée.
- Les arguments, bien que déclarés pointeurs dans les programmes appelés, sont dupliqués à l’appel. Ainsi, dans l’exemple, nous avons pu utiliser des constantes comme arguments dans la commande d’appel. Nous pouvons bien-sûr utiliser aussi des structures R comme arguments.
Exemple:
res <- 0
out <- .C("ma_sommeC", as.integer(1), as.integer(4), as.double(res))
res
[1] 0
res
n’est pas modifié en sortie. Le résultat est dans out
(voir le paragraphe Utilisation de Call pour éviter la duplication des arguments).
- Le retour des commandes
.C()
et.Fortran()
est une liste dont les composants sont les valeurs des arguments, dans l’ordre de ceux-ci. Pour que ces composants aient un nom, il faut les nommer dans la commande d’appel.
Exemple:
out <- .C("ma_sommeC", as.integer(1), as.integer(4), retour = as.double(res))
out$retour # la valeur de retour de la fonction ma_sommeC
2.5
Récapitulatif de l’exemple
-
Création du fichier
ma_sommeF.f
:subroutine ma_sommeF(a, b, res) integer a,b double precision res res = (a+b)/2.0 end
-
Création du fichier
ma_sommeC.c
:
void ma_sommeC(int *a, int *b, double *res)
{
*res=(double)(*a+*b)/2.0;
}
-
Création de la librairie
ma_somme.so
:R CMD SHLIB -o ma_somme.so ma_sommeC.c ma_sommeF.f
-
Chargement de la librairie sous R et utilisation:
dyn.load("ma_somme.so")
.C("ma_sommeC", as.integer(1), as.integer(4), retour = as.double(0))
.Fortran("ma_sommef_", as.integer(1), as.integer(4), retour = as.double(0))