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 :

[swig] Interfacer "const MyClass& obj" avec SWIG


Sujet :

Interfaçage autre langage Python

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur R&D en apprentissage statistique
    Inscrit en
    Juin 2009
    Messages
    447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur R&D en apprentissage statistique

    Informations forums :
    Inscription : Juin 2009
    Messages : 447
    Points : 752
    Points
    752
    Par défaut [swig] Interfacer "const MyClass& obj" avec SWIG
    Bonjour,

    Voici mon problème, j'ai une classe Matrix qui encapsule un tableau 1D et qui possède un constructeur comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<typename T>
    class Matrix {
    ...
       public:
       Matrix(int nrow, int ncol, double* data);
    ...
    }
    et des fonctions qui utilisent cette classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    double quelque_chose(const Matrix& mat);
    et j'aimerais créer un typemap pour pouvoir directement utiliser les tableaux numpy. En m'inspirant des typemaps de numpy je suis parvenu à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    %typemap(in,
             fragment="NumPy_Fragments")
      const Matrix< double >&
      (PyArrayObject* array=NULL, int is_new_object=0,Matrix<double> *new_mat=0 )
    {
      npy_intp size[2] = { -1, -1 };
      array = obj_to_array_contiguous_allow_conversion($input, NPY_DOUBLE,
                                                       &is_new_object);
      if (!array || !require_dimensions(array, 2) ||
          !require_size(array, size, 2)) SWIG_fail;
      new_mat = new Matrix<double>((size_t) array_size(array,0),(size_t) array_size(array,1), (double*) array_data(array));
      $1 = new_mat;
    }
    mais il y a deux problèmes (au moins):
    1. la matrice créée n'est pas détruite (fuite de mémoire)
    2. je suis obligé de créer un typemap par type de données


    Toute solution, piste, conseil seront les bienvenus.

    D'avance merci,

    Alexis.M

  2. #2
    Membre éclairé
    Homme Profil pro
    Ingénieur R&D en apprentissage statistique
    Inscrit en
    Juin 2009
    Messages
    447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur R&D en apprentissage statistique

    Informations forums :
    Inscription : Juin 2009
    Messages : 447
    Points : 752
    Points
    752
    Par défaut
    J'ai en fait trouvé une partie de la solution tout seul. Il suffit d'utiliser %freearg (oui, je sais, c'est fait pour ça) et d'utiliser $argnum pour avoir le bon nom de variable :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    %typemap(freearg) const Matrix< double >& {
        if (new_mat$argnum) delete new_mat$argnum;
    }
    et ça a le résultat attendu avec des fontions de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    double function(const Matrix< double >&m1, const Matrix< double >& m2);
    Pour en finir avec le problème existe-t-il une macro qui permettrait de prendre en argument un type de donnée et retournerait son code numpy ?

    Voilà...

  3. #3
    Membre éclairé
    Homme Profil pro
    Ingénieur R&D en apprentissage statistique
    Inscrit en
    Juin 2009
    Messages
    447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur R&D en apprentissage statistique

    Informations forums :
    Inscription : Juin 2009
    Messages : 447
    Points : 752
    Points
    752
    Par défaut
    Finalement, en copiant la manière de faire dans numpy.i, je suis arrivé au code suivant:

    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
     
    %define %Matrix_typemaps(DATA_TYPE,DATA_TYPECODE)
     
    %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
               fragment="NumPy_Macros")
      const Matrix< DATA_TYPE >&
    {
      $1 = is_array($input) || PySequence_Check($input);
    }
     
    %typemap(in,
             fragment="NumPy_Fragments") 
      const Matrix<DATA_TYPE>&
      (PyArrayObject* array=NULL, int is_new_object=0,Matrix<DATA_TYPE>* new_mat=0 )
    {
      npy_intp size[2] = { -1, -1 };
      array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
                                                       &is_new_object);
      if (!array || !require_dimensions(array, 2) ||
          !require_size(array, size, 2)) SWIG_fail;
      new_mat = new Matrix<DATA_TYPE>((size_t) array_size(array,0),(size_t) array_size(array,1), (DATA_TYPE*) array_data(array));
      $1 = new_mat;
    }
     
     
    %typemap(freearg) const Matrix< DATA_TYPE >& {
        if (new_mat$argnum) delete new_mat$argnum;
    }
    %enddef // %Matrix_typemaps()
    // Concrete instanciations of the macro %Matrix_typemaps()
     
    %Matrix_typemaps(signed char       , NPY_BYTE     )
    %Matrix_typemaps(unsigned char     , NPY_UBYTE    )
    %Matrix_typemaps(short             , NPY_SHORT    )
    %Matrix_typemaps(unsigned short    , NPY_USHORT   )
    %Matrix_typemaps(int               , NPY_INT      )
    %Matrix_typemaps(unsigned int      , NPY_UINT     )
    %Matrix_typemaps(long              , NPY_LONG     )
    %Matrix_typemaps(unsigned long     , NPY_ULONG    )
    %Matrix_typemaps(long long         , NPY_LONGLONG )
    %Matrix_typemaps(unsigned long long, NPY_ULONGLONG)
    %Matrix_typemaps(float             , NPY_FLOAT    )
    %Matrix_typemaps(double            , NPY_DOUBLE   )
    Ceci semble fonctionner quoique je je ne sache pas exactement ce que font toutes les fonctions. Quoiqu'il en soit je dois mériter un RTFM puisque j'ai répondu à mes propres questions...

    Je me pose toutefois des questions concernant:

    [/CODE]
    %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
    fragment="NumPy_Macros")
    [/CODE]

    qui semble vérifier qu'il s'agit d'un tableau de double. Ce code est celui trouvé dans numpy.i , que fait-il exactemement ?

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