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

PL/SQL Oracle Discussion :

Récupération pointeur d'une extproc C depuis PL/SQL


Sujet :

PL/SQL Oracle

  1. #1
    Membre éclairé Avatar de jkofr
    Homme Profil pro
    Senior Consultant DBA (Trivadis SA)
    Inscrit en
    Octobre 2006
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : Suisse

    Informations professionnelles :
    Activité : Senior Consultant DBA (Trivadis SA)
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 484
    Points : 724
    Points
    724
    Par défaut Récupération pointeur d'une extproc C depuis PL/SQL
    Hello,

    Je cherche a faire la chose suivante, cela pourra certainement sembler bizarre mais bon, j'expliquerai plus tard le but:-)

    Voici le test case:
    J'ai un module en c sous linux
    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
     
    #include <stdio.h>
     
    int gValue = 0;
     
    void setval(int val)
    {
    gValue = val;
    }
     
    int getval(void)
    {
     return (gValue);
    }
     
    int *getadrval(void)
    {
    return &gValue;
    }
     
    int getvalfromadr (int *adr)
    {
    return (*adr);
    }
    Compilation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    [oracle@server1 ~]$ gcc -fPIC -c test.c
    [oracle@server1 ~]$ gcc -shared -o test.so test.o

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    create or replace library c_test as '/home/oracle/test.so';
    /

    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
    create or replace procedure setval(val int) is
    external
    library sys.c_test
    name "setval"
    language C
    calling standard C;
    /
    
    create or replace function getval return int is
    external
    library sys.c_test
    name "getval"
    language C
    calling standard C;
    /
    
    create or replace function getvalfromadr (adr XXXX)  return int is
    external
    library sys.c_test
    name "getvalfromadr"
    language C
    calling standard C;
    /
    
    create or replace function getadrval return XXXX is
    external
    library sys.c_test
    name "getadrval"
    language C
    calling standard C;
    /
    Traitement souhaité:

    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
     
    set serveroutput on
    declare
    rc pls_integer;
    adr binary_integer;
    begin
     setval (10);  -- affectation de la valeur 10
     rc := getval; -- récupération de l avaleur
     dbms_output.put_line( 'rc='||rc);
     
     adr := getadrval; -- récupération de l’adresse de la variable globale
     rc := getvalfromadr (adr);-- récupération de la valeur à l'adresse de la variable globale
     dbms_output.put_line( 'rc='||rc);
     
    end;
    /

    Je n'arrive pas à récupérer le pointeur int*.
    Problème de typage?

    Merci de votre aide
    jko
    OCM 11g, RAC and Performance & Tuning Expert 11g
    RMAN Backup & Recovery, Data Guard and Grid Control

  2. #2
    Membre éclairé Avatar de jkofr
    Homme Profil pro
    Senior Consultant DBA (Trivadis SA)
    Inscrit en
    Octobre 2006
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : Suisse

    Informations professionnelles :
    Activité : Senior Consultant DBA (Trivadis SA)
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 484
    Points : 724
    Points
    724
    Par défaut
    Personne ne connais? :-(

    jko
    OCM 11g, RAC and Performance & Tuning Expert 11g
    RMAN Backup & Recovery, Data Guard and Grid Control

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Je n'ai même pas compris la question, et n'ai pas fait de C depuis 15 ans.
    Peut-être mnitu ?

  4. #4
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Bref la question est claire, depuis PL/SQL via une procédure externe écrite en C obtenir un pointer à un entier pour l'utiliser par la suite dans une autre fonction C manipulée elle aussi via PL/SQL, qui permettra à obtenir la valeur de l'entier. Le problème est que le PL/SQL ne permet pas de définir des variables de type pointeur à une exception, qui sont les ref curseurs.
    En théorie cela pouvait fonctionner parce-que un pointer n'est qu'une adresse numérique donc un type unsigned int. Mais j'ai de doute que ça marche vraiment de cette manière et j'aurais besoin d'un peu de temps pour tester. Par conséquence la question qui demeure est pourquoi faire, n'existe-il une méthode de contournement ? Sinon il faut se pencher un peu plus vers l'utilisation du OCI pour lequel je n'ai pas vraiment d'expérience.

  5. #5
    Membre éclairé Avatar de jkofr
    Homme Profil pro
    Senior Consultant DBA (Trivadis SA)
    Inscrit en
    Octobre 2006
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : Suisse

    Informations professionnelles :
    Activité : Senior Consultant DBA (Trivadis SA)
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 484
    Points : 724
    Points
    724
    Par défaut
    Citation Envoyé par mnitu Voir le message
    Bref la question est claire, depuis PL/SQL via une procédure externe écrite en C obtenir un pointer à un entier pour l'utiliser par la suite dans une autre fonction C manipulée elle aussi via PL/SQL, qui permettra à obtenir la valeur de l'entier. Le problème est que le PL/SQL ne permet pas de définir des variables de type pointeur à une exception, qui sont les ref curseurs.
    En théorie cela pouvait fonctionner parce-que un pointer n'est qu'une adresse numérique donc un type unsigned int. Mais j'ai de doute que ça marche vraiment de cette manière et j'aurais besoin d'un peu de temps pour tester. Par conséquence la question qui demeure est pourquoi faire, n'existe-il une méthode de contournement ? Sinon il faut se pencher un peu plus vers l'utilisation du OCI pour lequel je n'ai pas vraiment d'expérience.
    Voui!
    Voici dans les grandes lignes ou je veux en venir.

    L'objectif primaire est de créer une structure mémoire complexe (In memory Btree, IOT en qlq sort) pour stocker des relations complexes (cache fonctionnel ou cache métadonnées) en mémoire directement utilisable directement depuis Oracle en SQL ou PL/SQL.

    Les algos de la structure mémoire sont prêts mais maintenant je m'interroge sur la manière la plus pertinente de la faire. En C ou C++, le problème se résolve avec l'allocation de "shared mémory".
    Comment va se comporter ce concept avec le mapping mémoire réalisé via extproc?? C'est l’inconnue pour le moment.

    Je crois que le plus simple c'est de faire qlq tests :-)

    jko
    OCM 11g, RAC and Performance & Tuning Expert 11g
    RMAN Backup & Recovery, Data Guard and Grid Control

  6. #6
    Membre éclairé Avatar de jkofr
    Homme Profil pro
    Senior Consultant DBA (Trivadis SA)
    Inscrit en
    Octobre 2006
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : Suisse

    Informations professionnelles :
    Activité : Senior Consultant DBA (Trivadis SA)
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 484
    Points : 724
    Points
    724
    Par défaut
    Hello mnitu,

    Voici comment je vais gérer cela en utilisant de la shared memory!

    Le code C
    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
     
    #include <stdio.h>
    #include <sys/shm.h>
    #include <sys/stat.h>
     
     
    const int Seg_Size = 8192;
     
     
    int allocmem (char *address)
    {
      char *SharedMem;
      key_t SKey;
     
     
      int SegId = shmget (SKey, Seg_Size,IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
      SharedMem = (char*) shmat (SegId, 0, 0);
     
     
      sprintf(SharedMem, "My Shared memory! \n");
      sprintf (address,"shared memory attached at address %p with value =%s\n", SharedMem,SharedMem);
      shmdt (SharedMem);
      return SegId;
    }
     
     
    int freemem (int SegId)
    {
      shmctl (SegId, IPC_RMID, 0);
      return 0;
    }
     
     
    int getmem (int SegId, char *address)
    {
      char *SharedMem;
     
      SharedMem = (char*) shmat (SegId, 0, 0);
      sprintf (address,"shared memory attached at address %p with value =%s\n", SharedMem,SharedMem);
     
      shmdt (SharedMem);
      return 0;
    }

    Le code PL/SQL
    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
     
    create or replace library c_btree as '/home/oracle/btree.so';
    /
     
    create or replace function getmem (adr pls_integer , outstr out varchar2) return pls_integer is
    external
    library sys.c_btree
    name "getmem"
    language C
    calling standard C
    parameters(
    adr  unsigned  int,
    outstr string);
    /
     
    create or replace function allocmem (outstr out varchar2) return pls_integer is
    external
    library sys.c_btree
    name "allocmem"
    language C
    calling standard C
    parameters(
    outstr string);
    /
     
     
    create or replace function freemem (adr pls_integer) return pls_integer is
    external
    library sys.c_btree
    name "freemem"
    language C
    calling standard C;
    /

    Et le test case:


    Allocation mémoire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    set serveroutput on
    declare
    str varchar2(200);
    rc pls_integer := 0;
    begin
      rc := allocmem (str);
      dbms_output.put_line( ' str='||str||'  SegId='||rc);
    end;
    /
    str=shared memory attached at address 0x7f9e3ed0c000 with value =My Shared memory!
    SegId=4620318

    Accès à la shared memory à noter l'adresse qui est différente:-)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    set serveroutput on
    declare
    str varchar2(200);
    rc pls_integer := 0;
    begin
      rc := getmem (4620318,str);
      dbms_output.put_line( ' str='||str);
    end;
    /
    str=shared memory attached at address 0x7f20a1b34000 with value =My Shared memory!

    Libération mémoire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    set serveroutput on
    declare
    str varchar2(200);
    rc pls_integer := 0;
    begin
      rc := freemem (4620318);
    end;
    /
    PL/SQL procedure successfully completed.

    Si nouvelle accès à la shared mémory, ERREUR!


    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
     
    set serveroutput on
    declare
    str varchar2(200);
    rc pls_integer := 0;
    begin
      rc := getmem (4620318,str);
      dbms_output.put_line( ' str='||str);
    end;
    /
     
    declare
    *
    ERROR at line 1:
    ORA-28576: lost RPC connection to external procedure agent
    ORA-06512: at "SYS.GETMEM", line 1
    ORA-06512: at line 5
    Voilou.

    jko
    OCM 11g, RAC and Performance & Tuning Expert 11g
    RMAN Backup & Recovery, Data Guard and Grid Control

  7. #7
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Salut jkfor,

    Je vais essayer de digérer et tester tout ça un peut plus tard. Mais je trouve déjà que c'est une meilleur idée que d'essayer de récupérer des pointers en PL/SQL.

    Bon courage!

  8. #8
    Nouveau membre du Club
    Inscrit en
    Décembre 2006
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 37
    Points : 28
    Points
    28
    Par défaut
    Oui il est possible de récupérer l'adresse d'un pointeur C en PL/SQL.

    C'est assez simple. Il ne faut pas oublier qu'une adresse n'est ni plus ni moins qu'un entier.
    Donc, il est possible de faire une fonction C du genre :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    long get_myaddress()
    {
    return &shm;
    }
    Puis d'appeler cette fonction en PL/SQL et récupérer la valeur du pointeur.
    On peut ensuite utiliser cette valeur vers d'autres fonctions en C, du genre :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int ma_fonction( long shm_address )
    {
    Shm * shm = (Shm *) shm_address;
    ...
    shm->...
    ...
     
    return 0;
    }

  9. #9
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par themus Voir le message
    ...
    C'est assez simple. Il ne faut pas oublier qu'une adresse n'est ni plus ni moins qu'un entier.
    ...
    J'ai l'impression que vous n'avez ni bien lu ni bien compris cette discussion. Mais si vous voulez vous essayer reprenez le code posté tout en début de la discussion et essayez de le faire fonctionner sans utiliser la solution proposée par Jkofr par la suite.

Discussions similaires

  1. Réponses: 3
    Dernier message: 19/12/2014, 17h03
  2. [MySQL] Récupération d'un index pour BdD depuis une comboBox
    Par Tanoak_LaCapuche dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 25/06/2012, 11h46
  3. Réponses: 6
    Dernier message: 23/05/2011, 19h41
  4. Réponses: 2
    Dernier message: 13/09/2006, 18h39
  5. Réponses: 6
    Dernier message: 01/08/2006, 00h47

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