Connexion Perl envolée !?

kij_82 Messages postés 4089 Date d'inscription   Statut Contributeur Dernière intervention   -  
-
Bonjours à tous,

J'ai un gros problème dans mon programme dont voici l'exlication :
Ce programme mélange du C et du Perl, mais le probleme vient plus du Perl, donc...

J'ai le main en C suivant :
int main (int argc, char **argv, char **env)
{
	
	char *args[] = { "select * from question" };
	char *embedding[] = { "", "Bidon.pm" };
	time_t deb, fin;
	int arg = 2, i, j, nbligne, nbchamp;
	char ***retour;

	time(&deb);

	
    my_perl = perl_alloc();
//	PL_perl_destruct_level = 1;
    perl_construct(my_perl);
    perl_parse(my_perl, xs_init, arg, embedding, NULL);

	Connexion();

	retour = RqtPerl(args,sizeof(args) / sizeof(args[0]), &nbligne, &nbchamp);
    
    perl_destruct(my_perl);
    perl_free(my_perl);

	time(&fin);
	printf("Temp execution = %d secondes\n",fin-deb);

	printf("%d et %d\n",sizeof(**retour),sizeof(*retour));
	
	printf("\n\nEcriture du retour :\n\n");
	for(i=0; i< nbligne; i++){
		for(j=0; j < nbchamp; j++){
			printf("%s  ",retour[i][j]);
		}
		printf("\n");
	}	
}

Ce main a pour role d'établir l'environnement Perl donc et fait appel aux deux fonctions "Connexion" et "RqtPerl"

Voici le code de Connexion :
static void
	Connexion ( )
	{
	int count = 0;

		dSP;
		ENTER;
		SAVETMPS;
		PUSHMARK(SP);

		// Empilement des paramètres de connexion à la base :
		printf("%s %s %s %s\n",driver,base,pwd,user);
		XPUSHs(sv_2mortal(newSVpv(driver,0)));
		XPUSHs(sv_2mortal(newSVpv(base,0)));
		XPUSHs(sv_2mortal(newSVpv(user,0)));
		XPUSHs(sv_2mortal(newSVpv(pwd,0)));
		


		PUTBACK;

		count = perl_call_pv("connexion", G_SCALAR );
		printf("retour = %d\n",count);
		if( count == 1 ) {	printf("retour connexion\n"); connexion = POPs; }
		else {	connexion = NULL; printf("retour de connexion NULL\n"); }

		PUTBACK;
		FREETMPS;
		LEAVE;

		

	}


Cette fonction fait appel à la fonction Perl 'connexion' situé dans Bidon.pm et qui est chargé de créer un objet connexion (qui établi la connexion sur une DB).
La valeur retourné dans le C est une référence sur l'objet connexion créé et je la stocke dans une varable globale définie dans une .h :
SV *connexion

Voici le code de Bidon.pm et Connexion.pm :
Bidon.pm :
#!C:\Perl\bin\perl.exe


use strict;
use lib 'C:/Documents and Settings/stvivotn/Mes documents/essais/debug/';
use Rqt;
use Connexion;

sub connexion {
    # Réception des paramètres de connexion:
    my $DRIVER = shift;
    my $BASE = shift;
    my $USER = shift;
    my $PWD = shift;
    
    # Création d'une connexion à la base pour toute la durée du programme.
    my $connexion = Connexion->new($DRIVER,$BASE,$USER,$PWD);
    
    return \$connexion;
}

sub deconnexion {
    my ($self) = shift;
    $self->deconnexion();
    print "deconnexion";
}

sub lance {
    
    my $nb = @_;
    print "nb = $nb\n";
     my $connexion = shift;
     print "con = $connexion\n";
    my $i = 0;
    my $resultats;
    my @list;
    ####print "nb arguments de la liste = $nb\n";
    # Traitement des paramètres :
    while( $i < $nb )
    {
    print "boucle $i\n";
        my $sql = $_[$i++];
        # Recherche du mot clé de la requete:
        if( $sql =~ /select/ ) {
        print "entree select\n";
            my $rqt;
            
            ($rqt,@list) = Rqt->new(1,$sql,$connexion);
            #push(@list,$resultat);
            ###print "Nb lignes affectees par selection = $rqt :\n";
            if($rqt =~ /0E0/){  $rqt = 0;  }
        }
        elsif( $sql =~ /insert/ ) {
            my ($rqt) = Rqt->new(2,$sql,$connexion);
            if($rqt =~ /0E0/){  $rqt = 0;  }
            print "Nb lignes affectees par insertion = $rqt\n";
                        push(@list,$rqt);
        }
        elsif( $sql =~ /delete/ ) {
            my ($rqt) = Rqt->new(3,$sql,$connexion);
            if($rqt =~ /0E0/){  $rqt = 0;  }
            print "Nb lignes affectees par suppression = $rqt\n";
                        push(@list,$rqt);
        }
        elsif( $sql =~ /update/ ) {
            my ($rqt) = Rqt->new(4,$sql,$connexion);
            if($rqt =~ /0E0/){  $rqt = 0;  }
            print "Nb lignes affectees par update = $rqt\n";
            push(@list,$rqt);
        }
        else {
            print "Pas de correspondance de mot cle\n";
        }
    }

    return \@list;
}


Et Connexion.pm dont Bidon.pm fait appel :

package Connexion;
use DBI;
use strict;
use lib 'C:/Documents and Settings/stvivotn/Mes documents/essais/debug/';


##############################
# CONSTRUCTEUR               #
# @param :                   #
# driver / base / user / pwd #
##############################
sub new {
    #print "entre dans Connexion\n";
    my $classouref = shift;
    my $class = ref($classouref) || $classouref;
    
    print $class."\n";
    # vérification des arguments :
    
    my $nb = @_;
    print $nb."\n";
    die "Connexion intérrompue : Connexion::new : arg != 4\n" if ($nb != 4 );
    my($driver, $base, $user, $pwd) = @_;
    print "driver = $driver, base = $base, pwd = $pwd, user = $user\n";
    
    # tentative d'établissement de la connexion :
    my $dbh = DBI->connect("DBI:".$driver.":".$base,$user,$pwd, {RaiseError => 1, AutoCommit => 0 })
            or die $DBI::errstr;
    my $self = {};
    $self->{'connexion'}=$dbh;
    bless ($self, $class);
    
    # retourne l'identifiant de connexion brute et non un objet Connexion.
    return \$self;
}
sub get_connexion {
    my ($self) = shift;
    return ($self->{'connexion'});
}
sub deconnexion {
    my $self = shift;
    $self->{'connexion'}->disconnect();
}

1;


Voilà, donc, ensuite le code de la fonction C nommée 'RqtPerl' :
static char ***
    RqtPerl(char * arg[], int taille, int *nbligne, int *nbchamp)
    {
	
	  int count = 0, i = 0, j=0;
	  // Pointeur sur pointeur sur pointeur sur char retourné 
	  // par la fonction. Représente le tableau à double entrée
	  // des lignes retournée lors d'une requete de type 'SELECT' :
	  char ***tableau = NULL;
	  // Pointeur sur les éléments de la pile et du tableau 
	  // retourné par le Perl en cas de requete de type 'SELECT' :
	  SV *tmp, *champ;
	  AV *tab, *ligne;
		
	  // initialise le pointeur de pile
	  dSP;		
      ENTER;
	  // tout ce qui est cree a partir d'ici est une variable temporaire
      SAVETMPS;                        
	  // sauvegarde du pointeur de pile
      PUSHMARK(SP);                
	  
	  printf("connexion de la forme : %s\n",(char *)connexion);

	  // depos des requetes dans la pile :
	  XPUSHs(sv_2mortal(newSVsv(SvRV(connexion))));
	  while( i < taille )
		XPUSHs(sv_2mortal(newSVpv(arg[i++],0)));    

	  // rend global le pointeur local de pile 
      PUTBACK;                        

	  // appelle la fonction
      count = perl_call_pv("lance", G_ARRAY);
	  // rafraichit le pointeur de pile pour avoir les élément
	  // retourné par la fonction Perl 'lance' appellée.
      SPAGAIN;                          
                          
	  // Un objet est retourné sur la pile :
	  if(count != 0) {
		  printf("retour C = %d\n",count);
		// Onrécupère cet objet qui est de type tableau :
		tab = (AV *) SvRV(POPs);  
		
		*nbligne = av_len(tab)+1;
		tableau = malloc((*nbligne) * sizeof( **tableau) );

		i=0;
		while( i < (*nbligne) )
		{
			tmp = *av_fetch(tab, i, 0);
			if( SvTYPE(SvRV(tmp)) == SVt_NV ){
				printf("Entier de taille %d\n",SvLEN(tmp));
			}
			else if(SvTYPE(SvRV(tmp)) == SVt_PVAV ) {
				ligne = (AV *) SvRV(tmp);
				(*nbchamp) = av_len(ligne)+1;
				tableau[i] = malloc((*nbchamp) * sizeof( *tableau ));

				for( j=0; j<(*nbchamp); j++ ) {
					champ = *av_fetch(ligne, j, 0);
					tableau[i][j] = malloc( sizeof( SvLEN(champ) ) );
					strcpy(tableau[i][j], (char *)SvRV(champ)); 
				}
			}		
			i++;
		}
	  }

	  // retire la valeur de retour de la pile 
      PUTBACK;						   
	  // libere la valeur de retour
      FREETMPS;                            
	  // Et retire les arguments empiles 
      LEAVE;						   

	  // La liste des champ et des lignes est alors retournée avec
	  // pour valeur le résultat d'une requete select ou NULL :
	  return tableau;

    }

Cette fonction execute une ou plusieur requete passée ne paramètre.. cette fonction ne pose aucun probleme.
Elle appelle la fonction Perl 'lance' du fichier 'Bidon.pm' et dont le code est donné ci-dessus.
'lance' appelle d'autre fonction Perl située dans 'Connexion.pm' et dans 'Rqt.pm' dont voici le code :

Rqt.pm :
package Rqt;

use strict;
use lib 'C:/Documents and Settings/stvivotn/Mes documents/essais/debug/';

############################################
# CONSTRUCTEUR                             #
# @param :                                 #
# driver / base / user / pwd / [connexion] #
############################################

sub new {

    my $classouref = shift;
    my $class = ref($classouref) || $classouref;
    # vérification du nombre de paramètre passés au constructeur :
    my $nbparam = @_;
    die 'Usage : Rqt->new($mode,$requete,$connexion)\n' if($nbparam != 3);
    my $self = {};
    $self->{'mode'} = shift;      # mode requete
    $self->{'sql'} = shift;       # requete
    my $conn = shift;
    print "connexion dans rqt -> new = $conn\n";
    $self->{'connexion'} = $conn; # connexion base
    bless ($self, $class);
    $self->execute_sql();
}

sub execute_sql {
    my ($self) = shift;

    die 'Usage Rqt->execute_sql($connexion)\n' if( (my $nb = @_) != 0);
    my $ret;
    my ( $sth );

    eval {
        $sth = $self->{'connexion'}->get_connexion()->prepare( $self->{'sql'} );
        $ret = $sth->execute( );
    };
    die "Erreur d execution\n" if $@;

    # Si la requete est une selection, on retourne le nombre 
    # de ligne et le résultat de la sélection.
    if($self->{'mode'} == '1') {
        #my @list_champ = @{ $sth->{ NAME } };
        my @rqt_retour;    
        while ( my @row = $sth->fetchrow_array ) {
            push(@rqt_retour,\@row);
        }
        return ($ret,@rqt_retour);
    }
    else {  return $ret;  }
}

1;

Le but de ce fichier est la création d'u objet requete, puis l'éxécution de cette requete.. et c'est la que mon probleme survient en fait :

La requete ne peut pas s'éxécuter car l'objet de connexion qui est passé en paramètre à la fonction 'lance' de 'Bidon.pm' est <u>vide</u>!!
Cet objet connexion est créé comme je l'ai dit plus haut dans la première fonction C et est stocké dans la variable globale connexion (de type SV *).
Elle n'est pas nulle lorsque je la passe en paramètre à 'lance', et 'lance' recoit bien deux paramètres (la connexion et une requete). Seulement si je met une trace pour afficher le contenu de la variable '$connexion' récupérée au début de la fonction 'lance', rien ne s'affiche (valeur nulle donc..).

Je pense donc que je passe mal la connexion en paramètre, ou alors que je la récupère mal de ma première fonction, ou alors les deux (m'étonnerais pas !).

Je vous demande donc votre avis à tous la dessus, est-ce que vous voyez d'ou peut venir l'erreur ?

merci beaucoup d'avance.

++

6 réponses

m0n0-le-14r3 Messages postés 174 Date d'inscription   Statut Membre Dernière intervention   17
 
pouffff.... t'as vu ce que tu nous demandes de lire ??? on dirait la constitution
européenne ( trop long ) !!!--
-- je vis dans un rêve dont je ne me reveille jamais...--
<---- j adore ma voisine ;) ---->
0
kij_82 Messages postés 4089 Date d'inscription   Statut Contributeur Dernière intervention   857
 
trop long car tu ne caonnais pas le Perl mais pour qui sais le Perl, c'est relaltivement simple car il s'agit d'objet, méthodes, ... sauf peut etre pour la partie C ou c'est un peu plus barbare peut etre...
0

 
Faites ce que je dis mais pas ce que je fais...
http://www.commentcamarche.net/forum/affich-1514037-Puissance-4#1

++
0
kij_82 Messages postés 4089 Date d'inscription   Statut Contributeur Dernière intervention   857
 
Je sais bien mais la je suis tellement désespéré que je tente le tout pour le tout !!

Mon pb c'est comme si tu met une pomme de pin (que tu prend dans ton sceau) dans un tuyaux (non troué) en descente, que tu attend la pomme de pin en bas, mais jamais elle n'arrive... alors tu inspecte ton tuyaux... tu te dit, bon, ben elle doit etre par la... pis en fait faite plus de pomme de pin !!
La tu te dit "merde alors j'ai loupé un épisode !", des fois que, on ne sais jamais tu jette un oeil dans ton sceau et qu'es tu vois la au fond, tranquille en train de faire bronzette !!! Ta pomme de pin de merde !!

Bon ben voilà ou j'en suis arrivé.... au fond du sceau ! Je ne peux que lever les yeux au ciel et attendre un miracle de la vie...
0

 
mdr :-D

elle s'est bien foutue de ta gueule la pomme de pin...

par contre je savais pas qu'on pouvait appeler du C dans du perl. C'est fou ce qu'on peut faire avec ça quand même !

PS : et désolé j'ai lu ton code, mais je n'ai rien compris... donc peux po t'aider... bon courage quand même !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
kij_82 Messages postés 4089 Date d'inscription   Statut Contributeur Dernière intervention   857
 
lol, j'vois bien que t'a rien compris : c'est le C qui émule le Perl et non l'inverse, mais c'est vrai que tu peux faire l'inverse également ou les deux en même temps.

++
0

 
aaaaah ouais...

count = perl_call_pv("lance", G_ARRAY);
0