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) :
Mais ce n'est pas une bonne idée, car à chaque mise à jour il faut alors re-patcher le fichier original.
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 /* -------------------------------------------------------------------- */ /* 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;
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)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[]).
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 // 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"
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 };
Partager