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

Interfaçage autre langage Python Discussion :

python C API: convertir une struct C en Class python


Sujet :

Interfaçage autre langage Python

  1. #1
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Points : 54
    Points
    54
    Par défaut python C API: convertir une struct C en Class python
    Salut a tous,

    Nous voulons convertir une struct

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    typedef struct {
            PyObject_HEAD
            int first, second;
        } intpair;
    en une class (en suivant l'example 25.2 donne dans "Python in a Nutshell, 2nd Edition" )

    On obtient bien une class mais __dict__ montre une doc string vide et ne contient pas les membres "first" et "second"...
    De plus, la fonction d'initialisation intpair_init (voir plus bas) n'as pas l'air d'etre executee du tout car le commande printf de debuggage ne s'affiche pas

    1) Soit, on fait l'initialisation de maniere erronee.
    2) soit on a un problem avec l'ordre des champs dans PyTypeObject
    3) ou ???

    merci d'avance pous vos suggestions
    David, Juergen


    On utilise la definition de PyTypeObject a partir de usr/lib/python2.5/doc/commontex/typestruct.h (voir plus bas):
    et les fonctions intpair_dealloc,intpair_str, intpair_init.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    static int intpair_init(PyObject *self , PyObject *args, PyObject *kwds)
    {
      static char* nams[] = {"first","second",NULL};
      int first, second;
      printf("1 in init\n");fflush(stdout);
      if(!PyArg_ParseTupleAndKeywords(args, kwds, "ii", nams, &first, &second))
          return -1;
      ((intpair*)self)->first = 101;
      ((intpair*)self)->second = 102;
      printf("in init\n");
      return 0;
    }
    avec intpair_members:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    static PyMemberDef intpair_members[] = {
      {"first", T_INT, offsetof(intpair, first), 0, "first item" },
      {"second", T_INT, offsetof(intpair, second), 0, "second item" },
      {NULL}
    };
    l'initialisation est faite avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void initintpair(void)
    {
      static PyMethodDef no_methods[] = { {NULL} };
      PyObject* this_module = Py_InitModule("intpair", no_methods);
      PyType_Ready(&t_intpair);
      PyObject_SetAttrString(this_module, "intpair", (PyObject*)&t_intpair);
    }


    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
     
    static PyTypeObject t_intpair = {
     PyObject_HEAD_INIT(NULL)
      0,
      "intpair.intpair", /* For printing, in format "<module>.<name>" */
      sizeof(intpair),
      0, /* For allocation */
      /* Methods to implement standard operations */
      intpair_dealloc,
      0,
      0,
      0,
      0,
      intpair_str,
     /* Method suites for standard classes */
      0,
      0,
      0,
      /* More standard operations (here for binary compatibility) */
      0,
      0,
      0,
      PyObject_GenericGetAttr,
      PyObject_GenericSetAttr,
      /* Functions to access object as input/output buffer */
      0,
      /* Flags to define presence of optional/expanded features */
      Py_TPFLAGS_DEFAULT,
      "two ints (first,second)", /* Documentation string */
      /* Assigned meaning in release 2.0 */
      /* call function for all accessible objects */
      0,
      /* delete references to contained objects */
      0,
      /* Assigned meaning in release 2.1 */
      /* rich comparisons */
      0,
      /* weak reference enabler */
      0,
      /* Added in release 2.2 */
      /* Iterators */
      0,
      0,
      /* Attribute descriptor and subclassing stuff */
      0,
      intpair_members,
      0,
      0,
      0,
      0,
      0,
      0,
      intpair_init,
      PyType_GenericAlloc,
      PyType_GenericNew ,
      _PyObject_Del, /* Low-level free-memory routine */
      0,
      0,
      0,
      0,
      0,
      0
    };

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Pour répondre à la 1ère question:

    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
     
    class intpair(object):
        def __init__(self, first=0, second=0):
            self.first = first
            self.second = second
     
    # instanciation en laissant les valeurs par défaut first=0, second=0
    x = intpair()
     
    # modif des valeurs
    x.first = 42
    x.second = 75
     
    # instanciation avec initialisation first=5, second=10
    y = intpair(5,10)
     
    # accès aux valeurs de x:
    print x.first  # affiche 42
    print x.second  # affiche 75
    print y.first  # affiche 5
    print y.second  # affiche 10
    Les variables internes à la classe et préfixées par self appartiennent à l'instance de classe et sont accessibles avec le préfixe self dans toutes les méthodes de la classe.

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Points : 54
    Points
    54
    Par défaut
    merci pour ta reponse mais je voudrais initialiser les valeurs de "first" et "second"
    de la class a partir du code C et non pas dans python.

    en C, j'ai ajoute la ligne suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ((intpair*)self)->first = 101;
    dans la fonction intpair_init mais celle-ci ne semble pas etre appele.....

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Désolé, je n'ai aucune expérience sur le sujet.

    Voir la doc? => http://docs.python.org/ext/ext.html

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Points : 54
    Points
    54
    Par défaut
    merci je connais cet doc...mais elle est franchement pas terrible....

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Pour que init_intpair soit invoquée, il faut la déclarer comme ci-dessous dans la déclaration de la structure PyTypeObject :
    (initproc)init_intpair

    Un détail : appelle l'initialisation du module intpair comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
    #define PyMODINIT_FUNC void
    #endif
    PyMODINIT_FUNC initintpair(void)
    {
      static PyMethodDef no_methods[] = { {NULL} };
      PyObject* this_module = Py_InitModule("intpair", no_methods);
      PyType_Ready(&t_intpair);
      PyObject_SetAttrString(this_module, "intpair", (PyObject*)&t_intpair);
    }


    Sinon ton code est l'exemple de l'api C/Python .

    Si tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    python
    >>> import initpair
    >>> dir(intpair.intpair)
    et aussi
    tu devrais voir les membres déclarés de ta classe dans les deux cas.


    Remarque :
    Dans ton exemple de code, finalement ce n'est pas un "binding" de structure C mais la création d'un module en C contenant une classe .

  7. #7
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Points : 54
    Points
    54
    Par défaut
    merci bien de ta reponse !

    J'ai trouve un autre example (http://docs.python.org/ext/node23.html) qui correspond a tes suggestions et qui semble mieux fonctionner car le string "__doc__" est correctement initialisee.


    dans mon example en faisant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    python
    >>> import initpair
    >>> help(intpair)
    on voit bien que les membres "first" et "second" sont declares mais il n'y a pas de section "DATA" comme il y en a une pour help(sys) par example.

    et si je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    python
    >>> print initpair.first
    alors, python retourne une erreur en disant que first n'est pas un membre de intpair.....(AttributeError: 'module' object has no attribute 'first')
    ...surement due au fait que la section "DATA" est inexistant.

    alors, comment faire pour "remplir" les membres "first" avec la valeur 2 et "second" avec 3 a partir de C pour que, une fois retourne dans python, je puisse avoir:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    python
    >>> print initpair.first
    2
    >>>print initpair.first
    3
    merci d'avance

    David

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    D'après ton code, il faudrait plutôt faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    >>> import intpair
    >>> s = intpair.intpair(1, 2)
    >>> s.first
    1
    >>> s.second
    2

    first et second sont des variables membres de la classe intpair.intpair, pas des variables du module intpair.

  9. #9
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Points : 54
    Points
    54
    Par défaut
    oui d'accord, mais ca , c'est dans python....

    comment on fait la meme chose a partir du code C ?

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Si tu modifies la fonction init de la class initpair.initpair pour donner des valeurs par défaut à first et second :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    static int intpair_init(PyObject *self , PyObject *args)
    {
      int first = NULL;
      int second = NULL;
      if(!PyArg_ParseTuple(args, "|ii", &first, &second))
      {
        first = 0;
        second = 0;
      }
      ((intpair*)self)->first = first;
      ((intpair*)self)->second = second;
      return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    >>> import intpair
    >>> s = intpair.intpair()
    >>> s.first
    0
    >>> s.first = 3
    >>> s.first
    3

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Si tu veux une constante du module intpair :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
    #define PyMODINIT_FUNC void
    #endif
    PyMODINIT_FUNC
    initintpair(void)
    {
      static PyMethodDef no_methods[] = { {NULL} };
      PyObject* this_module = Py_InitModule("intpair", no_methods);
      PyType_Ready(&t_intpair);
      PyObject_SetAttrString(this_module, "intpair", (PyObject*)&t_intpair);
      PyModule_AddIntConstant(this_module, "constint", 16);
    }
    On ajoute la constante avec PyModule_AddIntConstant(PyObject* module, char* name, int i);

    On a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    >>> import intpair
    >>> intpair.constint
    16

  12. #12
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Points : 54
    Points
    54
    Par défaut
    merci bien ! c'est exactement ce que je voulais savoir. je n'ai pas encore eu le temps d'essayer, mais c'est a l'air d'etre ca.

    cheers

    Dave & Juergen

Discussions similaires

  1. Convertir une énumération Java en class C++
    Par yo0shii-78 dans le forum C++
    Réponses: 1
    Dernier message: 03/04/2015, 23h04
  2. Réponses: 0
    Dernier message: 18/03/2015, 10h23
  3. Réponses: 3
    Dernier message: 15/04/2014, 09h17
  4. [Python API] Appeller une fonction Python depuis le C++
    Par wetneb dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 18/10/2007, 12h49

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