Bonjour à tous.

Dans le cadre d'un vaste projet, on utilise habituellement SWIG pour permettre de faire des bindings de librairies C++ vers Java et C#.
La plupart du temps, ces binding, utilisant SWIG sont déjà fournis (GDal / LibTiff / LibGeotiff, etc).
Pour une libairie Shapefil ce binding SWIG n'est pas fourni.
Je cherche donc à savoir Comment accéder à un champ "int *" d'une structure C++ en le bindant vers int[] de java.
La compilation (makefile.vc) ainsi les fichiers shapelib_swig.i sont déja fournis.
Les précédents développeurs ne sont pas fait chier, ils ont directement modifiés le fichier original shapefil.h comme suit (je ne donne qu'une partie du fichier) :
Code :
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
/* -------------------------------------------------------------------- */
/*      SHPObject - represents on shape (without attributes) read       */
/*      from the .shp file.                                             */
/* -------------------------------------------------------------------- */
/* 
 * SWIG - TopoBase - pour traiter les tableaux padfX, padfY, padfZ et padfM ci-dessous, il faut donner une version modifiée du typemap
 * qui s'applique (on a sinon une erreur de compilation avec FillMeInAsSizeCannotBeDeterminedAutomatically car SWIG est incapable de calculer
 * la longueur du tableau
 * le typemap modifié utilise la longueur stockée dans nVertices
 */
typedef struct
{
    int		nSHPType;
 
    int		nShapeId; /* -1 is unknown/unassigned */
 
    int		nParts;
	/* SWIG - TopoBase - panPartStart et panPartType doivent être déclarés comme des tableaux de taille nParts */
#ifdef SWIG
%typemap(out) int[] 
%{$result = SWIG_JavaArrayOutInt(jenv, $1, (arg1)->nParts); %}
    int		panPartStart[];
    int		panPartType[];
#else
    int		*panPartStart;
    int		*panPartType;
#endif
 
    int		nVertices;
	/* SWIG - TopoBase - padfX, padfY, padfZ et padfM doivent être déclarés comme des tableaux de taille nVertices */
#ifdef SWIG
%typemap(out) double[] 
%{$result = SWIG_JavaArrayOutDouble(jenv, $1, (arg1)->nVertices); %}
    double	padfX[];
    double	padfY[];
    double	padfZ[];
    double	padfM[];
#else
    double	*padfX;
    double	*padfY;
    double	*padfZ;
    double	*padfM;
#endif
    double	dfXMin;
    double	dfYMin;
    double	dfZMin;
    double	dfMMin;
 
    double	dfXMax;
    double	dfYMax;
    double	dfZMax;
    double	dfMMax;
} SHPObject;
Mais ce n'est pas une bonne idée, car à chaque mise à jour il faut alors re-patcher le fichier original.
J'ai donc supprimé tous les #ifdef SWIG pour retrouver le code original et essayé de donner à SWIG les indications afin de transformer les appels pour que côté Java on utilise des int[] alors que côté C++ on a des int *
J'ai modifié le fichier shapelib_swig.h (compilé par makefile.vc)
Code :
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
// Module s'appelle org.shapelib.swig.shapelib
%module shapelib
 
// 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";
 
// Structure SHPObject => panPartStart et panPartType doivent être déclarés comme des tableaux de taille nParts
%typemap(out) int * panPartStart %{ $result = SWIG_JavaArrayOutInt(jenv, $1, (arg1)->nParts); %}
%typemap(out) int * panPartType  %{ $result = SWIG_JavaArrayOutInt(jenv, $1, (arg1)->nParts); %}
 
// padfX, padfY, padfZ et padfM doivent être déclarés comme des tableaux de taille nVertices
%typemap(out) double* padfX %{$result = SWIG_JavaArrayOutDouble(jenv, $1, (arg1)->nVertices); %}
%typemap(out) double* padfY %{$result = SWIG_JavaArrayOutDouble(jenv, $1, (arg1)->nVertices); %}
%typemap(out) double* padfZ %{$result = SWIG_JavaArrayOutDouble(jenv, $1, (arg1)->nVertices); %}
%typemap(out) double* padfM %{$result = SWIG_JavaArrayOutDouble(jenv, $1, (arg1)->nVertices); %}
 
// Include
%{ #include "../../../shapefil.h" %}
 
%include "../../shapefil.h"
Mais ça ne semble pas suffisant, le code Java généré attend toujours des SWIG_type_p_int pour accéder aux variables panPartStart et panPartType, ce qui est impossible à créer côté jave (en plus if faudrait modifier TOUT le code déjà existant qui y accède via des int[]).
Je lis la doc de SWIG qui est plus que fumeuse depuis 48h00 et je recherche sur internet ce genre de problème en java mais pour le moment je suis dans l'impasse.
J'aimerais simplement transformer les appels int * vers du int[] et ça serait bon.
Je ne sais pas comment faire, ni à quel moment les int * sont alloués / désalloués dans la structure (fuite mémoire)
Comment les copier, etc.
Je recherche des wiki simple sur le binding en java avec SWIG mais il y a peu de littérature et encore moins en Français (moins grave).
Si certains sont experts en SWIG je veux bien un peu d'aide.
Il y a aussi des fonctions avec des int * mais ça je les ai résolu avec
Code :
1
2
3
4
5
6
7
8
// on modifie 
//  - 'char * pszFieldName' en 'char * BYTE' pour appliquer un typemap défini dans various.i
//    qui va générer une interface java avec des tableaux de byte plutôt qu'un String 
//    (qui est "non mutable" et qui ne peut donc pas récupérer une valeur)
//  - 'int * pnWidth' et 'int * pnDecimals' en 'int * OUTPUT' pour appliquer un typemap défini dans typemaps.i
//    qui va générer une interface java avec des tableaux de int
%apply char *BYTE  { char * pszFieldName };
%apply int *OUTPUT { int * pnWidth, int * pnDecimals };