R C++

R et systèmes d'exploitation, configuration de R, gestion de la mémoire, construction des packages, interfaces entre R et d'autres logiciels, éditeurs pour R

Modérateur : Groupe des modérateurs

Crida Ameline
Messages : 5
Enregistré le : 07 Juil 2006, 10:23

R C++

Messagepar Crida Ameline » 07 Juil 2006, 12:29

Bonjour,

je souhaiterais importer du C++ dans R, pour accélerer mon programme, mais je n'y arrive pas, malgré toute la documentation de R. Je travaille sous windows, avec C++ builder. J'ai essayé, pour commencer, un exemple tout simple pris dans une aide sur R :

int add (int a, int b)
{
return a+b;
}

extern "C" {
void add_R(int *a, int *b, int *res)
{
*res=add(*a,*b);
}
}

et j'en ai fait une .dll à partir de C++ builder. Puis je l'importe sous R avec dyn.load, mais losrque j'appelle la fonction add_R avec .C, R me dit : "point d'entrée C "add_R" absent de la table de chargement" (et is.loaded("add_R") me répond FALSE). Et je ne comprends pas d'après la documentation comment créer un point d'entrée autrement que par extern "C".

Existe-t-il une procédure simple, pour importer du C++ sous windows ? est-il préférable que je change de compilateur C++, voire que je passe sous linux ?

De plus la fonction C++ qui me servira utilise une matrice (une classe
matrice dans C++ a été créée par celui qui a commencé le code en C++), qui sera importée depuis R, et renverra une autre matrice dans R, existe-t-il une méthode pas trop compliquée pour importer/exporter des matrices ?

Je vous remercie d'avance d'une réponse.

Ameline Crida

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Messagepar François Bonnot » 07 Juil 2006, 14:39

Bonjour,

Il y a peut-être des options de compilation à respecter.
Je ne connais pas C++ builder mais j'utilise Microsoft Visual C++ 6.0 sous Windows (nul n'est parfait).
L'exemple qui figure dans "Writing R Extensions" de l'aide de R comporte
1) La fonction C de calcul de convolution :

Code : Tout sélectionner

void convolve(double *a, int *na, double *b, int *nb, double *ab)
{
  int i, j, nab = *na + *nb - 1;
  for(i = 0; i < nab; i++)
    ab[i] = 0.0;
  for(i = 0; i < *na; i++)
    for(j = 0; j < *nb; j++)
      ab[i + j] += a[i] * b[j];
}

2) La fonction R qui appelle convolve :

Code : Tout sélectionner

conv <- function(a, b)
  {
    .C("convolve",
       as.double(a),
       as.integer(length(a)),
       as.double(b),
       as.integer(length(b)),
       ab = double(length(a) + length(b) - 1)
       )$ab
  }

Voici les lignes de commande que j'utilise (à partir d'une fenêtre DOS):

Code : Tout sélectionner

cl /MT /Ox /D "WIN32" /c *.c
link /dll /export:convolve /out:mypkg.dll *.obj

Ensuite sous R :

Code : Tout sélectionner

> dyn.load('mypkg.dll')
DLL name: mypkg
Filename: d:/R/Essais/mypkg.dll
Dynamic lookup: TRUE

Warning message:
DLL attempted to change FPU control word from 8001f to 9001f
> is.loaded('convolve')
[1] TRUE
> conv(1:3,4:5)
[1]  4 13 22 15


Donc à part le warning (que je ne comprends pas) ça marche.

Je suppose que pour passer des matrices en arguments il faut passer par pointeurs séparés leur contenu (donc un pointeur vers leur premier élément) et leurs dimensions, puis les reconstruire correctement.

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Messagepar Pierre Bady » 07 Juil 2006, 14:55

Bonjour,

je souhaiterais importer du C++ dans R, pour accélerer mon programme, mais je n'y arrive pas, malgré toute la documentation de R.


bienvenu au club :)

Voici une proposition pour faire une dll en C pour R :
Ceci reste une méthode "plus ou moins artisanale",
et mon C n’est pas très « fluent », I’m sorry … :)


Premier étape : les outils ….
- lire le "readme" et "readme.packages" localiser dans la “R home directory”
- installer PERL, MingGW (gcc+fortran compiler http://www.murdoch-sutherland.com/Rtools/)
- mise à jour des variables d’environnement.

Deuxième étape : le programme en C …
exemple avec la suite de Fibonacci
(issu en partie de la documentation de S-Pus 2000 … il me semble ?)
fichier .h :

Code : Tout sélectionner

# include <stdio.h>
# include <stdlib.h>

int fibiter(int a, int b, int c);
void fib(int*n);


fichier.c :

Code : Tout sélectionner

# include <stdio.h>
# include <stdlib.h>
# include"fib.h"
# include "R.h"
int fibiter(int a, int b, int c){
     if( c <= 0) return b;
     else return fibiter (a+b,a,c-1);
}
void fib(int*n){
     *n=fibiter(1,0,*n);
}


Troisième étape : compilation et construction de la librairie (console MS-dos)


Normalement :

Code : Tout sélectionner

Rcmd SHLIB fib.c


Si on n’a pas de chance (ce qui est mon (notre ?) cas):

- on a besoin de libR.a : vieille librairie issue des rw10NN = rw1051 ou rw1070, si besoin, j'en ai caché une version dans un coffre... :)
- copier les "include" de R dans les "include" de Mingwin

Code : Tout sélectionner

gcc --shared -o fib.dll fib.c libR.a


[EDIT] P.BADY le 31/07/2007
Pour le C, la librairie libR. a est inutile (cf les posts du dessous).
La ligne de commande suivante est suffisante:

gcc --shared -o fib.dll fib.c

Quatrième étape : chargement de la dll dans R

Une fois la bibliothèque construite, il ne reste plus qu'à l'appeler dans R.
Pour cela, on utilise la fonction dyn.load qui va permettre de charger la bibliothèque de fonctions. On utilise la fonction .C pour manipuler les fonctions de la DLL.

Code : Tout sélectionner

dyn.load("C:/your_directory/fib.dll")
fibo <-function(n) unlist(.C("fib",as.integer(n)))
sapply(1:10,function(x) fibo(x))
 [1]  1  1  2  3  5  8 13 21 34 55


(exemple testé sur les versions de R 2.0.0, R2.2.0 et R2.2.1)
cette procédure marche normalement aussi avec le fortran.
Par contre, je ne sais pas si cela permet de gérer des classes en C++ (*).
Il me semble que oui, mais je n’ai pas testé.

en espérant t'avoir aidé un peu :)

@+++

pierre

(*) C vs C++ … pas vraiment le même combat …. :)
PS: merci à Alex au passage pour la précieuse libR.a ... :)

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Messagepar Pierre Bady » 07 Juil 2006, 15:57

rebonjour,

voici un autre exemple avec le passage d'un vecteur de R vers C.
(l'exemple provient de : www.stat.nctu.edu.tw/MISG/SplusCallC.ppt)

code C:

Code : Tout sélectionner

# include <stdio.h>
# include <stdlib.h>
# include "R.h"


void arsim(double *x, long *n,double *phi)
{
long i;
for(i=1;i<*n;i++)
    x[i]=*phi * x[i-1] + x[i];
}


compilation:

Code : Tout sélectionner

gcc --shared -o Ar.dll Ar.c libR.a

[EDIT] P.BADY le 31/07/2007
Pour le C, la librairie libR. a est inutile (cf les posts du dessous).
La ligne de commande suivante est suffisante:

gcc --shared -o Ar.dll Ar.c

dans R :

Code : Tout sélectionner

dyn.load("C:/Documents and Settings/bad/Mes documents/Rdeveloppement/Ar.dll")
arsim <-function(x,a,b) .C("arsim",as.double(x),as.integer(a),as.integer(b))
x <- rnorm(10)
arsim(x,10,0.7)



ensuite du vecteur au tableau, il n'y a qu'un pas :)

en espérant t'avoir aidé un peu :)

@+++

pierre

Crida Ameline
Messages : 5
Enregistré le : 07 Juil 2006, 10:23

Messagepar Crida Ameline » 10 Juil 2006, 12:39

Bonjour,

merci beaucoup pour vos réponses très claires, je commence à mieux cerner le problème. Cependant, en répétant les opérations proposées, j'obtiens des messages d'erreur :

avec Rcmd SHLIB (sur tous les exemples testés, y compris fibonacci) il y a un pb au niveau du MAKE apparement :
Incorrect command line argument: --f
Je ne sais pas à quoi cela correspond. Est ce que ce genre d'erreur est connu ? Est ce qu'il pourrait s'agir du manque de la libR.a ?


et en compilant avec BorlandC++builder, comme cela est bien expliqué dans readme.packages, avec la commande

Code : Tout sélectionner

bcc32 -u- -6 -O2 -WDE convolve.c

d'abord il ne trouvait pas WDE, puis en supprimant cette option (pour essayer), l'erreur obtenue est
Unresolved external '_main' referenced from C:\Program Files\Borland\Cbuilder\Lib\COX32.obj
J'ai trouvé cette erreur sur internet et la méthode pour résoudre le problème a l'air plus qu'au dessus de mes moyens !

Bref, si quelqu'un a encore des idées, elles seront les bienvenues !
merci d'avance !

Ameline

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Messagepar Pierre Bady » 10 Juil 2006, 13:14

bonjour,

Je ne sais pas à quoi cela correspond. Est ce que ce genre d'erreur est connu ?


désolé ... je n'ai pas de réponse ... mais, de toute façon, je n'ai jamais réussi à utiliser la commande "Rcmd SHLIB...".

[EDIT] après quelques modifications dans mes variables d'environnement (path), la commande "R CMD SHLIB ..." fonctionne bien.
PATH=%GTK_BASEPATH%\bin;C:\Perl\bin\;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\programs\GTK\2.0\bin;C:\programs\MiKTeX 2.5\miktex\bin;C:\programs\MinGW\bin;C:\programs\Rtools\bin;C:\programs\R\R-2.4.1\bin;C:\programs\R\R-2.4.1\include;C:\programs\Rtools\bin;C:\programs\MinGW\include;C:\Program Files\QuickTime\QTSystem\;C:\programs\Rtools\bin;C:\Python25;C:\Program Files\Fichiers communs\ODBC\Data Sources;




Est ce qu'il pourrait s'agir du manque de la libR.a ?

nan... je ne pense pas.
la commande "Rcmd SHLIB" ne fonctionne pas chez moi (Makefile mal configuré, R mal installé, absence des codes sources, je suis peut-être complétement @#..!?:(... , je ne sais pas ???). Donc c'est pour cela que je n'utilise pas la commande "Rcmd SHLIB". A la place, j'utilise :

Code : Tout sélectionner

gcc --shared -o MaDLL.dll MaDLL.c libR.a


avec la "libR.a"qui est une vieille DLL qui date des versions 1.5.0/1.7.0 de R. Avec cette procedure, tu t'affranchis du Makefile et surement de quelques autres choses. C'est peut-être pas nécessairement un bien, mais en tout cas, ça simplifie pas mal nos affaires. Mais, ceci reste quand même une approche plus ou moins artisanale.

je n'ai jamais utilisé le compilateur C/C++ de bordland, donc sur ce point, je ne peux pas t'aider. Par contre, si tu utilises la libR.a avec le compilateur gcc, il faut bien penser à copier les "include" de R dans les "include" de Mingwin.

en espérant t'avoir aidé un peu :)

@+++

pierre

Crida Ameline
Messages : 5
Enregistré le : 07 Juil 2006, 10:23

Messagepar Crida Ameline » 10 Juil 2006, 13:26

merci beaucoup, ça marche maintenant, avec gcc effectivement, je l'avais complètement oublié ! et sans libR.a !

je vais pouvoir m'attaquer au gros du programme maintenant.

merci encore !

ameline

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Messagepar Pierre Bady » 10 Juil 2006, 13:27

rebonjour,

je viens tout juste trouver un document qui semble prometteur :

http://www.bichat.inserm.fr/equipes/Emi ... rindex.pdf

à voir, à lire ...

@++

Pierre

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Messagepar Pierre Bady » 10 Juil 2006, 13:30

rerebonjour,

merci beaucoup, ça marche maintenant, avec gcc effectivement, je l'avais complètement oublié ! et sans libR.a !


et sans "libR.a" ?
tu peux directement utiliser ta DLL dans R ?
Intéressant ... :o)

je vais tester aussi de mon coté :)

merci pour l'info

@+++

Pierre

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Messagepar Pierre Bady » 10 Juil 2006, 13:44

re... bonjour,

je viens de retester, les exemples sans la libR.a et ...je suis dèg ... :(
...et moi qui était tout fier de ma libR.a ....
bon ben ... en faite on n'en a pas besoin ...

par contre si vous utilisez du fortran, elle est nécessaire (j'espère...).
cette procédure était une adaptation d'une procédure utilisée avec g77 (fortran).


Après une visite chez les "fortranCompilerKillers", il semble que cette librairie sert juste pour les entrees/sorties en fortran ...
donc elle est inutile en C ... donc je suis désolé d'avoir donné une information erronée. :"(


@++ et bon courage pour la suite du programme :)

Pierre

PS: on peut donc considérer que le post est résolu ? ... :)
bravo, c'était un beau post :)

Crida Ameline
Messages : 5
Enregistré le : 07 Juil 2006, 10:23

Messagepar Crida Ameline » 10 Juil 2006, 14:54

:) comme ça tout le monde a appris quelque chose (enfin, surtout moi quand même !)

et effectivement, je crois que le post est résolu ...

merci encore !

ameline

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Messagepar Pierre Bady » 10 Juil 2006, 15:06

re...

comme ça tout le monde a appris quelque chose


Je pense que c’est le but de ce forum :)

@++ et merci à toi

Pierre

[EDIT] P.BADY, 14/08/2007
lien très intéressant sur le sujet :
http://www.mat.ulaval.ca/fileadmin/info ... 210607.pdf





PS : Et encore un petit pas de plus dans l’assouvissement de notre soif ardente de connaissance … >:D … dsl … Pierre --> []



Retourner vers « Archives : Environnement de R »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité