IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Firebird Discussion :

Runtime error avec UDF/DLL


Sujet :

SQL Firebird

  1. #1
    Membre du Club
    Inscrit en
    Août 2002
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 130
    Points : 58
    Points
    58
    Par défaut Runtime error avec UDF/DLL
    bonjour,

    j'ai ecrit 3 dll en delphi 6 contenant des fonctions appelées via des UDF contenu dans une base Firebird (1.5). Cela fonctionne plutot pas mal sauf que lorsque j'ai utilisé simultanement les DLLs en appelant les fonctions U
    DF via triggers/procedures stockées, j'ai le message ' runtime error 216 ' lorsque je me deconnecte de la base. Pour infos tous mes parametres de fonctions sont de types pchar. Suis je limité à une seule DLL contenant toutes mes fonctions ???

  2. #2
    Membre actif Avatar de TMuet
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Septembre 2003
    Messages
    225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 225
    Points : 288
    Points
    288
    Par défaut Re: Runtime error avec UDF/DLL
    Citation Envoyé par pram
    Suis je limité à une seule DLL contenant toutes mes fonctions ???
    Non

    Il y aurait plutôt un problème d'utilisation des PChar.
    Dans la mesure où les PChar sont des pointeurs, il est nécessaire que la référence soit maintenue (sinon ils ne pointeront plus sur rien du tout).
    Dans les UDF, on utilise ne général une variable locale à l'unité (globale en fait) qui est celle sur laquelle pointe la fonction.
    Ton RTE provient certainement de là

  3. #3
    Membre du Club
    Inscrit en
    Août 2002
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 130
    Points : 58
    Points
    58
    Par défaut
    merci de ta participation...toutes mes fonctions sont déclarés comme cela :
    interface
    function Mafonction (param1 : pchar) : pchar; stdcall;
    implementation
    function Mafonction (param1 : pchar) : pchar;
    Mon code

    par contre au niveau de la déclaration de l'UDF dans Firebird mon parametre est un CSTRING(xx) return by reference (FREE IT).
    En utilisant FREE IT j'ai cru comprendre que Firebird se chargeait de liberer la memoire ???

  4. #4
    Membre actif Avatar de TMuet
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Septembre 2003
    Messages
    225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 225
    Points : 288
    Points
    288
    Par défaut
    En tous cas, il faut utiliser cdecl et pas stdcall

  5. #5
    Membre du Club
    Inscrit en
    Août 2002
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 130
    Points : 58
    Points
    58
    Par défaut
    j'ai passé toute mes fonctions avec cdecl mais j'ai toujours le message lors de la deconnexion

  6. #6
    Membre du Club
    Inscrit en
    Août 2002
    Messages
    130
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 130
    Points : 58
    Points
    58
    Par défaut
    j'ai regroupé toutes les fonctions dans une et même seule DLL et je n'ai plus le message....et je comprends pas pourquoi...de ce fait j'ai peur que ça masque un autre probléme...

  7. #7
    Membre averti

    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 379
    Points : 376
    Points
    376
    Par défaut
    l'erreur 216 et probablement due à un problème de libération mémoire, plutôt que de bricoler avec des malloc et des "free it" il est plus sage d'utiliser ce type de structure, en voici un exemple, cela sera plus simple à comprendre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    DECLARE EXTERNAL FUNCTION CHR
            Smallint,
            CString(1)
            RETURNS PARAMETER 2
            ENTRY_POINT 'FCHR' MODULE_NAME 'udfsys2002';
     
    */
    UDFEXPORT void FCHR( short *Value, unsigned char *SOut )
    {
      if( ( Value ) && ( *Value >= 0 ) && ( *Value <= 255 ) )
        *SOut++ = (unsigned char)*Value;
     
      *SOut = 0;
    }
    j'utilise ce type de code depuis plusieurs années avec succès.

    et dans cet exemple, plus besoin de se prendre le choux de savoir qui libère quoi!

    un autre exemple plus complexe?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    DECLARE EXTERNAL FUNCTION BlobSubString
            BLOB,
            Integer,
            CString( 255 )
            RETURNS PARAMETER 3
            ENTRY_POINT 'FBlobSubString' MODULE_NAME 'udfsys2002';
     
    */
    UDFEXPORT void FBlobSubString( BLOBCALLBACK Blob,
                                   ISC_LONG *Offset, unsigned char *SOut )
    {
     
      ISC_USHORT     MaxLength = 255;  //taille maximale du morceau de texte à extraire
      ISC_USHORT     GetLength;        //longueur rapportée par la fonction
      unsigned char *Buffer;           //Buffer recevant les données du blob
      unsigned char *Src;              //pointeur d'extraction
      unsigned char *Cbl = SOut;       //pointeur d'écriture dans SOut
      int            Count = 0;        //nbre de caractère récupéré de la base
      ISC_USHORT     Dispo;            //Nbre de caractre extractible du buffer
      ISC_USHORT     Length;           //taille d'un segment
     
      //est-ce que la variable Blob contient autre chose que null?
      //et est-ce que le blob existe?
      if( ( !Blob ) || ( !Blob->blob_handle ) )
      {
       *SOut = 0; //chaîne vide
        return;
      }
     
      //cas ou que le point de départ excède le nombre de caractère
      //disponible dans le blob. ne pas oublier que le point de
      //départ commence à 0!
      if ( Blob->blob_total_length < *Offset )
      {
       *SOut = 0; //chaîne vide
        return;
      }
     
     
      //cas ou le point de départ est inférieure à 0 (erreur)
      if( *Offset < 0 )
        *Offset = 0;
     
      //allocation du buffer de réception, car il est possible que les
      //segments du blob soivent plus grand que la chaîne en résultat.
      Length = (ISC_USHORT)Blob->blob_max_segment;
     
      //allocation du buffer de réception des données
      Buffer = (unsigned char *) malloc( Length + 1 );
     
      //acquisition du premier segment de blob
      while( ( Blob->blob_get_segment( Blob->blob_handle, Buffer, Length, &GetLength ) ) )
      {
        //a t'on atteind le point d'extraction?
        //si pas, alors charge le 2ème segment et suivant
        if( ( Count + GetLength ) < *Offset )
        {
          //comptabilise le nombre de caractère déjà récupéré depuis la base
          Count += GetLength;
          continue;
        }
     
        //pointeur de lecture dans le buffer
        Src = Buffer + *Offset - Count;
     
        //calcul le nombre de caractère disponible dans le buffer
        Dispo = (ISC_USHORT)( Buffer + GetLength - Src );
     
        //transfert les données
        for( ; MaxLength && Dispo; MaxLength--, Dispo--, Cbl++, Src++ )
          *Cbl = *Src;
     
        //au 2ème tour et suivant, le point de départ est à 0, entendu que
        //la totalité du buffer est utilisable, dès le 1er caractère.
        *Offset = 0;
     
      } //while( ( Blob->blob_get_segment( Blob->blob_handle, Buffer, Length, &GetLength ) ) )
     
      //termine la chaîne
      *Cbl = 0;
     
      //terminé, libère le buffer
      free( (void *)Buffer );
     
    }
    j'ai d'autres trucs du genre, si tu en veux, "yaka"

Discussions similaires

  1. Runtime error avec tcp::acceptor.bind()
    Par Nekkro dans le forum Boost
    Réponses: 4
    Dernier message: 13/12/2011, 08h11
  2. Runtime Error avec une dll
    Par gandf dans le forum C#
    Réponses: 3
    Dernier message: 15/09/2010, 23h17
  3. Runtime error avec API Windows
    Par PP(Team) dans le forum Windows
    Réponses: 2
    Dernier message: 10/04/2007, 11h45
  4. Réponses: 2
    Dernier message: 24/01/2007, 13h58
  5. [Kylix] Runtime error 230 avec INDY
    Par Anonymous dans le forum EDI
    Réponses: 2
    Dernier message: 23/03/2002, 11h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo