Appeler du C, du C++ ou du Fortran depuis R. Notions de base

Auteur.e.s
Annie Bouvier, Inra
Résumé

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 utilise Call voir la fiche Appeler du C, du C++ ou du Fortran depuis R: notions avancées) ou Rcpp.

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

  1. 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
  2. Création du fichier ma_sommeC.c:

void ma_sommeC(int *a, int *b, double *res)
{
 *res=(double)(*a+*b)/2.0;
}
  1. Création de la librairie ma_somme.so:

    R CMD SHLIB -o ma_somme.so ma_sommeC.c ma_sommeF.f
  2. 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))
Versions des outils utilisés
R version 3.4.2 (2017-09-28)
Thèmes de la fiche
Thèmes