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

Autres éditeurs Discussion :

SWIG utiliser un StringBuilder au lieu d'un String


Sujet :

Autres éditeurs

  1. #1
    Membre habitué

    Inscrit en
    Février 2007
    Messages
    250
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Février 2007
    Messages : 250
    Points : 162
    Points
    162
    Par défaut SWIG utiliser un StringBuilder au lieu d'un String
    Bonkour à tous.

    J'utilise SWIG pour utiliser une librairie C en JAVA.
    Problème, certains champs utilisés sont des "char *" dans lequel le code C vient écrire une string.
    Or, SWIG me map ça avec un String en argument de méthode :

    L'appel de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DBFFieldType SHPAPI_CALL DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName, int * pnWidth, int * pnDecimals );
    Devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      public static DBFFieldType DBFGetFieldInfo(DBFInfo psDBF, int iField, String pszFieldName, SWIGTYPE_p_int pnWidth, SWIGTYPE_p_int pnDecimals) {
        return DBFFieldType.swigToEnum(shapelibJNI.DBFGetFieldInfo(DBFInfo.getCPtr(psDBF), psDBF, iField, pszFieldName, SWIGTYPE_p_int.getCPtr(pnWidth), SWIGTYPE_p_int.getCPtr(pnDecimals)));
      }
    Bien entendu ça ne fonctionne pas, on ne peut modifier une String passée en paramètre !
    Pourtant celà semble avoir marché un jour avec un Java plus ancien Bizarre).

    Je cherche donc à mapper le char * (et pas le const char * qui lui fonctionne bien puisqu'il n'est qu'en lecture côté C) avec un StringBuilder.

    J'ai bien tenté des trucs dans mon fichier .i :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    %typemap(ctype)    char * "StringBuilder"
    %typemap(imtype)   char * "StringBuilder"
    %typemap(javatype) String "StringBuilder"
     
    %javamethodmodifiers DBFGetFieldInfo "private";
    %rename(DBFGetFieldInfo_private) DBFGetFieldInfo;
     
    %pragma(java) modulecode=%{ 
      public static DBFFieldType DBFGetFieldInfo(DBFInfo psDBF, int iField, StringBuilder sbFieldName, SWIGTYPE_p_int pnWidth, SWIGTYPE_p_int pnDecimals) {
        byte[] arBytes = new byte[11];
        return DBFGetFieldInfo_private(psDBF, iField, arBytes, pnWidth, pnDecimals);
      }
    %}
    Ça me laisse le loisir de mettre le code que je veux entre le monde java et le jni... Mais par contre, ça ne me génère pas la bonne fonction.
    Dans le java :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      public static DBFFieldType DBFGetFieldInfo(DBFInfo psDBF, int iField, StringBuilder sbFieldName, SWIGTYPE_p_int pnWidth, SWIGTYPE_p_int pnDecimals) {
        byte[] arBytes = new byte[11];
        return DBFGetFieldInfo_private(psDBF, iField, arBytes, pnWidth, pnDecimals);
      }
      private static DBFFieldType DBFGetFieldInfo_private(DBFInfo psDBF, int iField, String pszFieldName, SWIGTYPE_p_int pnWidth, SWIGTYPE_p_int pnDecimals) {
        return DBFFieldType.swigToEnum(shapelibJNI.DBFGetFieldInfo_private(DBFInfo.getCPtr(psDBF), psDBF, iField, pszFieldName, SWIGTYPE_p_int.getCPtr(pnWidth), SWIGTYPE_p_int.getCPtr(pnDecimals)));
      }
    Et dans le shapelibJNI :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public final static native int DBFGetFieldInfo_private(long jarg1, DBFInfo jarg1_, int jarg2, String jarg3, long jarg4, long jarg5);
    On voit bien qu'au niveau du JNI c'est toujours un String qui est passé et au au niveau de DBFGetFieldInfo_private idem donc ça n'a aucune chance de fonctionner !

    Ça doit pourtant être simple !!

  2. #2
    Membre habitué

    Inscrit en
    Février 2007
    Messages
    250
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Février 2007
    Messages : 250
    Points : 162
    Points
    162
    Par défaut
    Après avoir galéré 48h00, ouf ça marche !!!!
    Voilà le fichier shapelib_swig.i :
    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    %module shapelib
     
    /*
    Voir le message ici : https://www.developpez.net/forums/d1271455/c-cpp/outils-c-cpp/autres-outils-c-cpp/swig-conversion-int-cpp-vers-int-java/
     
    various.i permet l'utilisation de : 
      "char * BYTE" pour traiter un char * comme un tableau de byte plutôt que comme une String (qui est "non mutable")
    typemaps.i permet l'utilisation de INPUT et OUTPUT 
    */
     
    %include "arrays_java.i";
    %include "various.i";
    %include "typemaps.i";
    %include cpointer.i
    %pointer_functions(int, intp);
    %include carrays.i
     
    // Très important pour tous les accesseurs array de type int / double
    %array_functions( double, double_array )
    %array_functions( int,    int_array )
     
    //======================================================================================================
    /* 
     * const char *CONST_BYTE typemaps. 
     * These are input typemaps for mapping a Java byte[] array to a C char array.
     * Note that as a Java array is used and thus passeed by reference, the C routine 
     * can return data to Java via the parameter.
     *
     * Example usage wrapping:
     *   void foo(char *array);
     *  
     * Java usage:
     *   byte b[] = new byte[20];
     *   modulename.foo(b);
     */
    // Modifier les 'const char *' coté JNI (coté C) pour la dll "shapelibjni.dll" : fichier "shapelibjni.c"
    %typemap(jni) const char *CONST_BYTE "jstring"
     
    // Les trois prochaines méthodes sont utilisées au sein du JNI (côté C) pour récupérer / relâcher les données de ce type
    %typemap(in) const char *CONST_BYTE {
      $1 = (const char *) JCALL2(GetStringUTFChars, jenv, $input, 0);
    }
    %typemap(argout) const char *CONST_BYTE {
      JCALL2(ReleaseStringUTFChars, jenv, $input, (const char *) $1);
    }
    %typemap(freearg) const char *CONST_BYTE ""
     
    // Modifie les const char * dans le fichier shapelibJNI.java
    %typemap(jtype) const char *CONST_BYTE "String"
     
    // Modifie les const char * dans le fichier shapelib.java
    %typemap(jstype) const char *CONST_BYTE "String"
     
    %apply const char * CONST_BYTE  { const char * };
    //======================================================================================================
    //======================================================================================================
    /* 
     * char *PSZ_BYTE typemaps. 
     * These are input typemaps for mapping a Java byte[] array to a C char array.
     * Note that as a Java array is used and thus passeed by reference, the C routine 
     * can return data to Java via the parameter.
     *
     * Example usage wrapping:
     *   void foo(char *array);
     *  
     * Java usage:
     *   byte b[] = new byte[20];
     *   modulename.foo(b);
     */
    // Modifier les 'char *' coté JNI (coté C) pour la dll "shapelibjni.dll" : fichier "shapelibjni.c"
    %typemap(jni) char *PSZ_BYTE "jbyteArray"
     
    // Les trois prochaines méthodes sont utilisées au sein du JNI (côté C) pour récupérer / relâcher les données de ce type
    %typemap(in) char *PSZ_BYTE
    {
      $1 = (char *) JCALL2(GetByteArrayElements, jenv, $input, 0);
    }
    %typemap(argout) char *PSZ_BYTE
    {
      JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *) $1, 0); 
    }
    %typemap(freearg) char *PSZ_BYTE ""
     
    // Modifie les 'char *' coté JNI (coté Java) dans le jar "shapelib.jar" : fichier "shapelibJNI.java"
    %typemap(jtype) char *PSZ_BYTE "byte[]"
     
    // Modifie les const char * dans le fichier shapelib.java (fonction privée)
    %typemap(jstype) char *PSZ_BYTE "byte[]"
     
    // Appliquer ces règles pour char * pszFieldNamen si un autre s'appelle pareil est est non const ça ne fonctionnera peut-être pas.
    %apply char * PSZ_BYTE  { char * pszFieldName };
     
    // Passer la fonction en privé, j'ai des traitements à faire pour appeler cette fonction
    %javamethodmodifiers DBFGetFieldInfo "private";
    %rename(DBFGetFieldInfo_private) DBFGetFieldInfo; // <- Modifie le nom DBFGetFieldInfo en DBFGetFieldInfo_private dans le fichier "shapelibJNI.java" + "shapelibjni.c"
     
    %pragma(java) modulecode=%{
      public static DBFFieldType DBFGetFieldInfo(DBFInfo _psDBF, int _iField, StringBuilder _sbFieldName, SWIGTYPE_p_int _pnWidth, SWIGTYPE_p_int _pnDecimals) {
      byte[] _arrBytes = new byte[12];
      DBFFieldType ret = DBFGetFieldInfo_private(_psDBF, _iField, _arrBytes, _pnWidth, _pnDecimals);
     
      // Convert string result into string and add into StringBuilder
      ConvertByteToStringbuilder(_arrBytes, _sbFieldName);
     
      return ret;
    }
    %}
     
    // Pour importer dans la classe JNI
    %pragma(java) jniclassimports=%{
    %}
     
    %pragma(java) modulecode=%{
      /**
       * Convert byte[] to String into StringBuilder.
       *
       * @param _arrInput Input string into array of bytes.
       * @param _sbOutput String builder to fill.
       */
      private static void ConvertByteToStringbuilder(byte[] _arrInput, StringBuilder _sbOutput)
      {
        // Clear StringBuilder content
        _sbOutput.setLength(0);
     
        // CharBuffer implements CharSequence interface, which StringBuilder fully support in it's methods
        java.nio.charset.Charset charset = java.nio.charset.Charset.forName("UTF-8");
        java.nio.charset.CharsetDecoder decoder = charset.newDecoder();
     
        // ByteBuffer.wrap simply wraps the byte array, it does not allocate new memory for it
        java.nio.ByteBuffer srcBuffer = java.nio.ByteBuffer.wrap(_arrInput);
     
        //Now, we decode our srcBuffer into a new CharBuffer (yes, new memory allocated here, no can do)
        java.nio.CharBuffer resBuffer;
        try
        {
          resBuffer = decoder.decode(srcBuffer);
          _sbOutput.append(resBuffer.toString());
        }
        catch (java.nio.charset.CharacterCodingException _e)
        {
          _e.printStackTrace();
        }
      }
    %}
    //======================================================================================================
     
    %{
      #include "../../../shapefil.h"
    %}
     
    %include "../../shapefil.h"
     
    %array_class(int, intArray);

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utiliser /bin/sh au lieu de bash
    Par Miksimus dans le forum Shell et commandes GNU
    Réponses: 12
    Dernier message: 25/10/2006, 13h57
  2. Utiliser une variable au lieu de perdre du temp?
    Par mejrs dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 22/10/2006, 11h56
  3. Réponses: 3
    Dernier message: 03/05/2006, 15h08
  4. [swig] utilisation de ld sous mac osX tiger.
    Par PyBio dans le forum Interfaçage autre langage
    Réponses: 3
    Dernier message: 26/10/2005, 17h51
  5. Utiliser des procédures au lieu des classes
    Par ahage4x4 dans le forum ASP
    Réponses: 5
    Dernier message: 29/06/2005, 10h53

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