Utilisation de GeographicLib sous Visual Studio C++

Je vous livre ici la solution à un problème qui m’a donné pas mal de fil à retordre : l’utilisation de la librairie GeographicLib (une bibliothèque de calcul de coordonnés géographique, notamment du « direct geodesic problem« , qui consiste à calculer une positon sur la Terre en connaissant une positon d’origine, une distance et un azimut(cap). Cette bibliothèque est également capable de faire des conversions entre les différents systèmes géodesiques existants). Je précise que la version utilisées ici est la 1.14

Mes problèmes furent multiples :

  1. Faire fonctionner la bibliothèque sous Visual Studio (2008 pour mon cas, mais les soucis auraient probablement étés les mêmes sous VS2005 ou VS2010)
  2. Comprendre comment elle fonctionne
  3. Réussir à compiler, en l’occurrence, j’avais des erreurs sur l »édition des liens (linker).

1) Installer et faire fonctionner la librairie sous VC2008

Pas de grosses difficultés ici, il faut juste ne pas se faire piéger par la doc qui présente (à ce jour) une erreur. Donc :

  • dans les paramètres du projet (Projet -> Propriété de…),
  • se rendre dans Propriété de configuration ->C/C++->Général->Autres répertoire include et renseigner : C:Program FilesGeographicLib-1.14include.
  • Dans Éditeur de liens->Général-> Répertoires de bibliothèques supplémentaires, renseigner C:Program FilesGeographicLib-1.14lib et non C:Program FilesGeographicLib-1.14include comme indiqué dans la documentation
  • Dans Éditeur de liens->Entrée->Dépendances supplémentaires, ajouter Geographic.lib
Je vais tâcher de les contacter pour leur indiquer cette erreur.

2) Comprendre comment elle fonctionne

Ici, j’ai eu des difficultés, car c’est l’une des premières fois que j’utilise une bibliothèque tierce (hors Qt, superbe doc,  et SDK matériels, qui ont souvent eut aussi une doc assez explicite avec des exemples), et assez peu utilisée. J’ai donc eu un mal terrible à trouver des exemples sur Internet. Lors de mes premiers essais, j’ai ainsi codé ainsi :

double lat1 = 46.908848;
double lon1 = 6.327472;
double azi1 = 59.16;
double s12 = 6216.28;
double lat2;
double lon2;
Geodesic::Direct(lat1, lon1, azi1, s12, &lat2, &lon2);

Ce qui générait à la compilation des erreurs du genre :

.main.cpp(295) : error C2665: 'GeographicLib::Geodesic::Direct' : aucune des 6 surcharges n'a pu convertir tous les types d'arguments
.GeographicLib/Geodesic.hpp(350): peut être 'GeographicLib::Math::real GeographicLib::Geodesic::Direct(GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real &,GeographicLib::Geodesic::real &) throw() const'

Je vous livre donc la syntaxe correcte qui est :

double lat1 = 46.908848;
double lon1 = 6.327472;
double azi1 = 59.16;
double s12 = 6216.28;
double lat2;
double lon2;
const Geodesic& g = Geodesic::WGS84;
g.Direct(lat1, lon1, azi1, s12, lat2, lon2);

3) Parvenir à compiler/linker

A la compilation, enfin, à l’édition des liens pour être précis, j’obtenais les erreurs suivantes :

1>Édition des liens en cours...
1>Geographic.lib(Geodesic.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_MSC_VER=1600' non valide rencontrée ; ignorée
1>Geographic.lib(Geodesic.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0' non valide rencontrée ; ignorée
1>Geographic.lib(GeodesicLine.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_MSC_VER=1600' non valide rencontrée ; ignorée
1>Geographic.lib(GeodesicLine.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0' non valide rencontrée ; ignorée
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: char const * __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::c_str(void)const " (?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::erase(unsigned int,unsigned int)" (?erase@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@II@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: static unsigned int __cdecl std::char_traits<char>::length(char const *)" (?length@?$char_traits@D@std@@SAIPBD@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>Geographic.lib(Geodesic.obj) : error LNK2019: symbole externe non résolu "__declspec(dllimport) void __cdecl std::_Xlength_error(char const *)" (__imp_?_Xlength_error@std@@YAXPBD@Z) référencé dans la fonction "public: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Xlen(void)const " (?_Xlen@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEXXZ)
1>Geographic.lib(Geodesic.obj) : error LNK2019: symbole externe non résolu "__declspec(dllimport) void __cdecl std::_Xout_of_range(char const *)" (__imp_?_Xout_of_range@std@@YAXPBD@Z) référencé dans la fonction "public: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Xran(void)const " (?_Xran@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEXXZ)

Après pas mal de lecture sur le net et avoir bidouillé a peu près tous les paramètres de l’éditeur de liens de Visual Studio, je me suis résolu à recompiler moi même la librairie. Pour cela, il faut télécharger le zip du code source de GeographicLib (ici par exemple). Les développeurs ont même eu l’idée de fournir des fichiers projets pour VS2005 (GeographicLib-vc8.sln), 2008 (GeographicLib-vc9.sln) et 2010 (GeographicLib-vc10.sln) (répertoire windows de l’archive). J’ouvre donc le fichier qui correspond à ma version de Visual Studio et j’ai compilé la bibliothèque en mode Release. Il en ressort un beau fichier .lib d’environ 1800 ko (contre 1300 ko pour celui fourni). Après remplacement du fichier Geographic.lib fourni par ce nouveau fichier, la compilation et l’édition des liens se déroule à merveille, et la bibliothèque semble fonctionner.

Dans mon immense bonté, je vous fourni cette librairie compilée avec Visual Studio C++ 2008 (je ne sais pas si elle fonctionne avec VC2005 ou VC2010) : Geographic.lib.

Tags: , , ,

3 Responses to Utilisation de GeographicLib sous Visual Studio C++

  1. Charles Karney says:

    Thank you for trying GeographicLib and documenting the
    problems you ran into…

    (1) The errors in the documentation on how to use GeographicLib
    with your software in Visual Studio should now be fixed. I’d
    appreciate it if you could confirm this.

    (2) Good point. I plan to include very simple examples of how
    to use each class. For a preview, see

    http://geographiclib.sf.net/html/classGeographicLib_1_1Geodesic.html#details

    I will add examples for the other classes over the course of the
    next 2 months.

    (3) This method will work Visual Studio 2005, 2008, and 2010 on
    Windows. For other compilers, you will need to use the cmake
    configuration. For example, using cmake you can use the mingw
    compiler that comes with Qt, so that your Qt applications
    (compiled with mingw) can link against GeographicLib.

    • Clément says:

      1) Yes this issu is now fixed ! I will edit my article later.
      2) Very usefull idea to include at least one example by class.
      3) Thank you for providing visial studio project with source code archive it is very helpfull !
      Thank for this very usefull and practicle library.

  2. Charles Karney says:

    The latest version of GeographicLib, v1.17, includes a simple example for each class.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *