Erreur lors de la génération des bindings java

Utilisation de Xcas

Modérateur : xcasadmin

vgu
Messages : 8
Inscription : mar. mai 14, 2024 5:17 pm

Erreur lors de la génération des bindings java

Message par vgu » mer. mai 15, 2024 12:47 pm

Bonjour

Je rencontre une erreur en compilant les bindings java. Sur debian 12.5, je fais :

Code : Tout sélectionner

wget https://www-fourier.univ-grenoble-alpes.fr/~parisse/giac/giac_stable.tgz
tar xvzf giac_stable.tgz
cd  giac-1.9.0/
./configure
make
cd src
swig -c++ -java -package giac -outdir javagiac giac.i && \
     g++ -c -fpic giac_wrap.cxx  -I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux
La compilation renvoie une liste d'erreurs, concernant des fonctions manquantes (writewave, readwav) ou des paramètres des fonctions:

Code : Tout sélectionner

giac_wrap.cxx: In function ‘_jstring* Java_giac_giacJNI_gen_1printcharptr(JNIEnv*, jclass, jlong, jobject)’:
giac_wrap.cxx:3179:47: error: ‘const class giac::gen’ has no member named ‘printcharptr’
 3179 |   result = (char *)((giac::gen const *)arg1)->printcharptr();
      |                                               ^~~~~~~~~~~~
giac_wrap.cxx: In function ‘jboolean Java_giac_giacJNI_is_1known_1rootof(JNIEnv*, jclass, jlong, jlong, jobject, jlong, jobject)’:
giac_wrap.cxx:6217:69: error: invalid initialization of reference of type ‘const giac::vecteur&’ {aka ‘const giac::dbgprint_vector<giac::gen>&’} from expression of type ‘giac::gen’
 6217 |   result = (bool)giac::is_known_rootof((giac::vecteur const &)*arg1,*arg2,arg3);
      |                                                                     ^~~~~
In file included from giac.h:34:
alg_ext.h:46:57: note: in passing argument 2 of ‘bool giac::is_known_rootof(const vecteur&, const vecteur&, gen&, const context*)’
   46 |   bool is_known_rootof(const vecteur & v,const vecteur &lv,gen & symroot,GIAC_CONTEXT);
      |                                          ~~~~~~~~~~~~~~~^~
giac_wrap.cxx: In function ‘jlong Java_giac_giacJNI_alg_1evalf(JNIEnv*, jclass, jlong, jobject, jlong, jobject, jlong, jobject)’:
giac_wrap.cxx:6246:78: error: conversion from ‘giac::context*’ to ‘const giac::gen’ is ambiguous
 6246 |   result = giac::alg_evalf((giac::gen const &)*arg1,(giac::gen const &)*arg2,arg3);
      |                                                                              ^~~~
In file included from giac.h:7:
gen.h:662:5: note: candidate: ‘giac::gen::gen(int128_t)’ (near match)
  662 |     gen(int128_t i);
      |     ^~~
gen.h:662:5: note:   conversion of argument 1 would be ill-formed:
giac_wrap.cxx:6246:78: error: invalid conversion from ‘giac::context*’ to ‘int128_t’ {aka ‘__int128’} [-fpermissive]
 6246 |   result = giac::alg_evalf((giac::gen const &)*arg1,(giac::gen const &)*arg2,arg3);
      |                                                                              ^~~~
      |                                                                              |
      |                                                                              giac::context*
gen.h:659:5: note: candidate: ‘giac::gen::gen(longlong)’ (near match)
  659 |     gen(longlong i);
      |     ^~~
gen.h:659:5: note:   conversion of argument 1 would be ill-formed:
giac_wrap.cxx:6246:78: error: invalid conversion from ‘giac::context*’ to ‘longlong’ {aka ‘long long int’} [-fpermissive]
 6246 |   result = giac::alg_evalf((giac::gen const &)*arg1,(giac::gen const &)*arg2,arg3);
      |                                                                              ^~~~
      |                                                                              |
      |                                                                              giac::context*
gen.h:658:5: note: candidate: ‘giac::gen::gen(long int)’ (near match)
  658 |     gen(long i);
      |     ^~~
gen.h:658:5: note:   conversion of argument 1 would be ill-formed:
giac_wrap.cxx:6246:78: error: invalid conversion from ‘giac::context*’ to ‘long int’ [-fpermissive]
 6246 |   result = giac::alg_evalf((giac::gen const &)*arg1,(giac::gen const &)*arg2,arg3);
      |                                                                              ^~~~
      |                                                                              |
      |                                                                              giac::context*
gen.h:652:5: note: candidate: ‘giac::gen::gen(size_t)’ (near match)
  652 |     gen(size_t i): type(_INT_),subtype(0),val((int)i)  {
      |     ^~~
gen.h:652:5: note:   conversion of argument 1 would be ill-formed:
giac_wrap.cxx:6246:78: error: invalid conversion from ‘giac::context*’ to ‘size_t’ {aka ‘long unsigned int’} [-fpermissive]
 6246 |   result = giac::alg_evalf((giac::gen const &)*arg1,(giac::gen const &)*arg2,arg3);
      |                                                                              ^~~~
      |                                                                              |
      |                                                                              giac::context*
gen.h:647:5: note: candidate: ‘giac::gen::gen(int)’ (near match)
  647 |     gen(int i): type(_INT_),subtype(0),val(i) {
      |     ^~~
gen.h:647:5: note:   conversion of argument 1 would be ill-formed:
giac_wrap.cxx:6246:78: error: invalid conversion from ‘giac::context*’ to ‘int’ [-fpermissive]
 6246 |   result = giac::alg_evalf((giac::gen const &)*arg1,(giac::gen const &)*arg2,arg3);
      |                                                                              ^~~~
      |                                                                              |
      |                                                                              giac::context*
alg_ext.h:50:56: note: in passing argument 3 of ‘giac::gen giac::alg_evalf(const gen&, const gen&, const gen&, const context*)’
   50 |   gen alg_evalf(const gen & a,const gen &b,const gen & c,GIAC_CONTEXT);
      |                                            ~~~~~~~~~~~~^
giac_wrap.cxx: In function ‘jlong Java_giac_giacJNI_common_1minimal_1POLY(JNIEnv*, jclass, jlong, jobject, jlong, jobject, jlong, jobject, jlong, jobject, jlong, jlong, jobject)’:
giac_wrap.cxx:6348:106: error: cannot convert ‘giac::context*’ to ‘const giac::vecteur*’ {aka ‘const giac::dbgprint_vector<giac::gen>*’}
 6348 |   result = giac::common_minimal_POLY((giac::gen const &)*arg1,(giac::gen const &)*arg2,*arg3,*arg4,*arg5,arg6);
      |                                                                                                          ^~~~
      |                                                                                                          |
      |                                                                                                          giac::context*
alg_ext.h:53:96: note:   initializing argument 6 of ‘giac::gen giac::common_minimal_POLY(const gen&, const gen&, gen&, gen&, int&, const vecteur*, const context*)’
   53 |   gen common_minimal_POLY(const gen & ga,const gen & gb, gen & a,gen & b,int &k,const vecteur *l,GIAC_CONTEXT);
      |                                                                                 ~~~~~~~~~~~~~~~^
giac_wrap.cxx: In function ‘jlong Java_giac_giacJNI_integrate_1gen_1rem(JNIEnv*, jclass, jlong, jobject, jlong, jobject, jlong, jobject, jlong, jobject)’:
giac_wrap.cxx:9540:92: error: invalid conversion from ‘giac::context*’ to ‘int’ [-fpermissive]
 9540 |   result = giac::integrate_gen_rem((giac::gen const &)*arg1,(giac::gen const &)*arg2,*arg3,arg4);
      |                                                                                            ^~~~
      |                                                                                            |
      |                                                                                            giac::context*
giac_wrap.cxx:9540:35: error: too few arguments to function ‘giac::gen giac::integrate_gen_rem(const gen&, const gen&, gen&, int, const context*)’
 9540 |   result = giac::integrate_gen_rem((giac::gen const &)*arg1,(giac::gen const &)*arg2,*arg3,arg4);
      |            ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from giac.h:22:
intg.h:68:7: note: declared here
   68 |   gen integrate_gen_rem(const gen & e, const gen & x, gen & remains_to_integrate,int intmode,GIAC_CONTEXT);
      |       ^~~~~~~~~~~~~~~~~
giac_wrap.cxx: In function ‘jlong Java_giac_giacJNI_integrate_1id_1rem(JNIEnv*, jclass, jlong, jobject, jlong, jobject, jlong, jobject, jlong, jobject)’:
giac_wrap.cxx:9576:34: error: too few arguments to function ‘giac::gen giac::integrate_id_rem(const gen&, const gen&, gen&, const context*, int)’
 9576 |   result = giac::integrate_id_rem((giac::gen const &)*arg1,(giac::gen const &)*arg2,*arg3,arg4);
      |            ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
intg.h:70:7: note: declared here
   70 |   gen integrate_id_rem(const gen & e, const gen & x, gen & remains_to_integrate,GIAC_CONTEXT,int intmode);
      |       ^~~~~~~~~~~~~~~~
giac_wrap.cxx: In function ‘jlong Java_giac_giacJNI_linear_1integrate(JNIEnv*, jclass, jlong, jobject, jlong, jobject, jlong, jobject, jlong, jobject)’:
giac_wrap.cxx:9612:91: error: invalid conversion from ‘giac::context*’ to ‘int’ [-fpermissive]
 9612 |   result = giac::linear_integrate((giac::gen const &)*arg1,(giac::gen const &)*arg2,*arg3,arg4);
      |                                                                                           ^~~~
      |                                                                                           |
      |                                                                                           giac::context*
giac_wrap.cxx:9612:34: error: too few arguments to function ‘giac::gen giac::linear_integrate(const gen&, const gen&, gen&, int, const context*)’
 9612 |   result = giac::linear_integrate((giac::gen const &)*arg1,(giac::gen const &)*arg2,*arg3,arg4);
      |            ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
intg.h:71:7: note: declared here
   71 |   gen linear_integrate(const gen & e,const gen & x,gen & remains_to_integrate,int intmode,GIAC_CONTEXT);
      |       ^~~~~~~~~~~~~~~~
giac_wrap.cxx: In function ‘jlong Java_giac_giacJNI__1readwav(JNIEnv*, jclass, jlong, jobject, jlong, jobject)’:
giac_wrap.cxx:11759:18: error: ‘_readwav’ is not a member of ‘giac’
11759 |   result = giac::_readwav((giac::gen const &)*arg1,arg2);
      |                  ^~~~~~~~
giac_wrap.cxx: In function ‘jlong Java_giac_giacJNI__1writewav(JNIEnv*, jclass, jlong, jobject, jlong, jobject)’:
giac_wrap.cxx:11781:18: error: ‘_writewav’ is not a member of ‘giac’; did you mean ‘_writergb’?
11781 |   result = giac::_writewav((giac::gen const &)*arg1,arg2);
      |                  ^~~~~~~~~
      |                  _writergb

Est-ce qu'il y a eu quelques changements du côté giac sans modiciation de javagiac, ou bien j'ai manqué une étape ?

Par ailleurs, j'utilisais (il y a une dizaine d'années...) des binaires précompilés, assez pratiques pour packager sans devoir compiler moi même pour toutes les plateformes. J'en ai cherché des version récentes et j'ai trouvé:

Code : Tout sélectionner

https://www-fourier.ujf-grenoble.fr/~parisse/giac/javagiac_win32.tgz
https://www-fourier.ujf-grenoble.fr/~parisse/giac/javagiac_win64.tgz
https://www-fourier.ujf-grenoble.fr/~parisse/giac/javagiac_linux32.tgz
https://www-fourier.ujf-grenoble.fr/~parisse/giac/javagiac_linux64.tgz
https://www-fourier.ujf-grenoble.fr/~parisse/giac/java_mac.tgz
Mais je n'ai pas vu de mention de date ou de version. Sont-ils à jour ?

Merci !

parisse
Messages : 5880
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: Erreur lors de la génération des bindings java

Message par parisse » mer. mai 15, 2024 1:04 pm

Les bindings java ne sont pas du tout à jour. Il va falloir faire des modifications dans giac.i qui date d'il y a presque 10 ans, à moins que Geogebra en ait une version plus à jour.
Par exemple la déclaration de is_known_rootof et alg_evalf devrait etre (cf. alg_ext.h)

Code : Tout sélectionner

  bool is_known_rootof(const giac::vecteur & v,const giac::vecteur & lv,gen & symroot,giac::context * );
  gen alg_evalf(const gen & a,const gen &b,const gen & c,giac::context * );
Je ne maintiens plus de binaires précompilés sous Linux, c'est devenu trop compliqué avec toutes les distributions et incompatibilités. Par contre Giac/Xcas est un paquet standard des distributions majeures Linux, donc la librairie devrait facilement etre accessible.
Sous windows, la version mingw64 utilise une DLL il me semble, donc ca pourrait aussi fournir ce qu'il faut.
Sur Mac, je n'ai pour l'instant qu'une solution où l'utilisateur compile (avec les outils de brew) et installe.

parisse
Messages : 5880
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: Erreur lors de la génération des bindings java

Message par parisse » mer. mai 15, 2024 1:13 pm

Je n'ai pas trouvé de giac.i chez Geogebra, par contre ils ont un giac_wrap.cxx qui doit etre à jour:
https://github.com/geogebra/giac/blob/m ... c_wrap.cxx
Je ne sais pas dans quelle mesure le sous-répertoire jni en entier pourrait vous servir, si vous le souhaitez, je peux poser la question à l'équipe de dev de Geogebra, il faudrait juste leur donner quelques précisions sur l'usage que vous allez en faire, je pense qu'ils seront prets à nous dépanner pour un projet d'accessibilité!

vgu
Messages : 8
Inscription : mar. mai 14, 2024 5:17 pm

Re: Erreur lors de la génération des bindings java

Message par vgu » mer. mai 15, 2024 3:03 pm

Merci pour votre réponse rapide.

C'est noté pour les bindings java. J'avais commencé par regarder du côté du dépot github de geogebra/giac sans succès. Je vais d'abord essayer de voir si je peux faire rapidement moi même les modifications adéquates pour mettre à jour les signatures des fonctions.

(Au passage, à propos de ce dépôt, j'ai mis un moment pour comprendre qu'il ne s'agissait pas de mêmes sources de giac que celles que vous distribuez en tar.gz sur votre site. Peut-être serait-il bon de l'indiquer dans le README de geogebra/giac ?)

Pour les binaires, peut être serait-il possible de les produire via l'intégration continue proposée par certaines plateformes de dépôt de sources ? Je regarde si c'est faisable.

parisse
Messages : 5880
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: Erreur lors de la génération des bindings java

Message par parisse » mer. mai 15, 2024 3:12 pm

vgu a écrit :
mer. mai 15, 2024 3:03 pm
(Au passage, à propos de ce dépôt, j'ai mis un moment pour comprendre qu'il ne s'agissait pas de mêmes sources de giac que celles que vous distribuez en tar.gz sur votre site. Peut-être serait-il bon de l'indiquer dans le README de geogebra/giac ?)
Ca devrait être les mêmes fichiers sources .cc et .h, mais agencés différemment, geogebra place les .cc et les .h dans des répertoires différents et utilise son propre système de build.
Pour les binaires, peut être serait-il possible de les produire via l'intégration continue proposée par certaines plateformes de dépôt de sources ? Je regarde si c'est faisable.
C'est un aspect que je ne maitrise absolument pas...

vgu
Messages : 8
Inscription : mar. mai 14, 2024 5:17 pm

Re: Erreur lors de la génération des bindings java

Message par vgu » jeu. mai 16, 2024 10:36 am

Dans la version tar.gz, j'ai pu corriger les 7 fonctions qui posaient problème,

Code : Tout sélectionner

// supprimé 
// const char * printcharptr() const ;
// gen _readwav(const gen & g,giac::context * );
// gen _writewav(const gen & g,giac::context * );

// remplacé
// gen integrate_gen_rem(const gen & e, const gen & x, gen & remains_to_integrate,giac::context * );
gen integrate_gen_rem(const gen & e, const gen & x, gen & remains_to_integrate,int intmode,giac::context *);
// gen integrate_id_rem(const gen & e, const gen & x, gen & remains_to_integrate,giac::context * );
gen integrate_id_rem(const gen & e, const gen & x, gen & remains_to_integrate, giac::context *,int intmode);
// gen common_minimal_POLY(const gen & ga,const gen & gb, gen & a,gen & b,int &k,giac::context * );
gen common_minimal_POLY(const gen & ga,const gen & gb, gen & a,gen & b,int &k,const giac::vecteur *l,giac::context *);
Avec ça, je peux produire un fichier giac_wrap.cxx qui compile ... mais à l'éxecution, la machine java plante:

Code : Tout sélectionner

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007ff0c8dcd39a, pid=2311860, tid=2311885
#
# JRE version: OpenJDK Runtime Environment (17.0.11+9) (build 17.0.11+9-Debian-1deb12u1)
# Java VM: OpenJDK 64-Bit Server VM (17.0.11+9-Debian-1deb12u1, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# C  [libjavagiac.so+0xeb39a]  giac::gen::~gen()+0x4a
C'est pourtant bien la même lib giac.so qui est utilisée pour compiler et exécuter. Je n'ai pas d'idée de solution.

Dans la version github.com/geogebra/giac.git

Note:Il faut impérativement utiliser java11 (et pas au dessus), que plus aucune distribution ne propose par défaut, sans quoi gradle refusera de s’exécuter.

Je peux produire libgiac.so et libjavagiac.so mais par contre, comme il n'y a pas le .i je ne peux pas produire les interfaces java correspondantes (celles produites par swig). Donc, même s'il y a un fichier giac_wrap.cxx dans le répertoire, je ne peux pas les utiliser dans un programme java.

Du coup, je suis bloqué. Si vous avez des idées, je suis preneur !

A propos de la version js/wasm
A terme, giac serait intégré dans notre éditeur en ligne pour jouer le rôle d'une "calculatrice braille". Donc je peux soit le mettre du côté serveur (écrit en java), comme je l'imaginais initialement, soit du côté client (javascript). Pour décharger le serveur, et puisque la production de l'interface java n'est pas maintenue, je pensais essayer la seconde solution. Mais je vois que les builds de giac en javascript ou en wasm font plusieurs Mo. Est-ce qu'il est possible à votre avis de produire une version qui ne contiendrait que le strict minimum (seulement les opérations mathématiques et le parseur, rien d'autre) et qui aurait une taille plus réduite (de l'ordre d'1 Mo max.) ?

Merci !

parisse
Messages : 5880
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: Erreur lors de la génération des bindings java

Message par parisse » lun. mai 20, 2024 5:08 pm

Sur le segfault, il faudrait en savoir plus en utilisant gdb, donc lancer l'application puis gdb et faire un attach sur le process. Ceci étant, mes connaissances en java sont essentiellement nulles, donc ça risque de ne pas donner beaucoup d'informations. Sur la version java utilisée par geogebra, j'ai l'impression qu'ils vont arrêter de la maintenir un jour, en basculant tout sur wasm/javascript.
Sur la version wasm/javascript, je compile exprès en un seul fichier js, ce qui prend presque 2 fois plus de place qu'une version en 2 fichiers js et wasm, mais permet une utilisation complètement en local, sans avoir à mettre en place un serveur local, et cela génère en fait très peu de trafic Internet, j'ai même souvent des problèmes parce qu'il faut explicitement effacer le cache du navigateur lorsque je fais une mise à jour de giacwasm.js. Je vous encourage à tester avec cette version, essayer de faire une version minimale de giac est possible, c'est ce que je fais pour diverses calculatrices (où on n'a pas le choix la place en ROM est limitée), mais cela demande pas mal de travail au-delà de 20 à 30% de gain, risque d'engendrer des bugs, et ça permettrait sans doute de gagner un facteur 3, mais pas un facteur 10. A l'heure actuelle, charger 18Mo, c'est au maximum 20 secondes sur de l'ADSL, ensuite le fichier est dans le cache du navigateur, donc faire ce travail ne me semble pas être la meilleure stratégie (d'autant que ça peut potentiellement priver un utilisateur très bon en maths d'accéder à des fonctions plus évoluées de giac), je pense qu'il vaut mieux garder ce temps de développement pour faire autre chose.

parisse
Messages : 5880
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: Erreur lors de la génération des bindings java

Message par parisse » lun. mai 20, 2024 5:43 pm

Pour générer giacwasm.js, le source est https://www-fourier.univ-grenoble-alpes ... c_wasm.tgz, je compile avec emscripten 1.38.41. On doit pouvoir gagner un peu de place sans perdre grand chose en fonctionnalité en supprimant #define HAVE_LIBPARI et #define HAVE_LIBGLPK 1 dans config.h. On peut aussi enlever le support de mpfr et mpfi mais ça ne va pas gagner grand chose. On peut aussi supprimer le support de MicroPython et de QuickJS en enlevant -DMICROPY_LIB -DQUICKJS de CXXFLAGS dans le Makefile.

vgu
Messages : 8
Inscription : mar. mai 14, 2024 5:17 pm

Re: Erreur lors de la génération des bindings java

Message par vgu » mar. mai 21, 2024 5:20 pm

Merci beaucoup pour vos réponses.

Je comprends que la piste wasm/js semble être vraiment à privilégier si je ne veux pas prendre la responsabilité de la maintenance des bindings.

Les connections ne sont pas super bonnes partout dans le monde, et 20 secondes, cela peut être dissuasif, surtout pour une première connexion. Ceci dit, dans la majorité des cas, ce sera ressenti comme instantané par l'utilisateur et pour les autres, faire le chargement en arrière-plan accompagné par quelque chose comme une barre de défilement séduisante pourrait faire passer la pilule. Et c'est effectivement beaucoup plus raisonnable de ne pas avoir à maintenir une version de mon côté.

Concernant la question du cache à supprimer lors de la mise à jour, il est possible de configurer les paramètres de fetch/xhttprequest pour contrôler le cache https://developer.mozilla.org/en-US/doc ... uest/cache à partir du js. (mais pas sûr que ça réponde à votre problématique).

Répondre