Programme avec Postgresql

Bonjour à  tous,



Voilà  plusieurs fois que je tente sans succès de réaliser un programme utilisant Postgresql. Je dois en être à  ma 3 ou 4eme tentative, cette fois c'est la bonne... Ayant pas toujours beaucoup de temps disponible j'ai laché l'affaire la dernière fois à  cause de la difficulté à  utiliser Xcode et Postgresql.



Postgresql m'est indispensable car je veux une base de données multi-utilisateurs et gratuite... Je n'en connais pas d'autres. Mon projet sera d'abord pour un usage personnel mais il est toujours possible qu'un jour je le vende.



Donc je commence mon projet, installe Postgresql. Déjà  première surprise Xcode sait où trouver libpq, puisque je n'ai aucune erreur si je fais un include... Je veux faire un premier test, est-ce qu'Xcode trouve bien la bibliothèque C libpq pour que j'utilise les fonctions C d'accès aux bases de données ?



Premier problème j'ai dû sélectionner LLVM GCC 4.2 sinon...
<br />
error: -fobjc-arc is not supported with fragile abi<br />


J'ai trouvé la solution sur le net, mais je ne sais absolument pas ce qu'est ce machin qui a l'air fragile image/wink.png' class='bbc_emoticon' alt=';)' /> ... bref, je suis totalement amateur, aucune formation en informatique mais j'ai pas mal programmé en PHP et je suis bien dégrossi en Objective-C même si je souffre du syndrome amateur : il manque des bases...



Bref je n'ai plus l'erreur sus-cité en mettant LVM GCC 4.2 mais je suis preneur de l'explication...



Autre bug surprenant, Xcode crée tout seul un AppDelegate dans lequel il crée un @property (assign) IBOutlet NSWindow *window; mais sans créer la variable d'instance !!! Bug... je la crée et c'est bon, mais je subodore qu'un truc m'échappe non ?



Enfin je teste pour voir si je peux facilement accéder aux fonction C :



.h
<br />
#import &lt;Foundation/Foundation.h&gt;<br />
#include &quot;libpq-fe.h&quot;<br />
<br />
@interface GVMaclasse : NSObject {<br />
   <br />
    NSString *nom;<br />
}<br />
@property (assign) NSString *nom;<br />
- (void) connect;<br />
@end<br />




C'est juste un test j'aurais pu virer la variable d'instance pour l'instant.

.m
<br />
#import &quot;GVMaclasse.h&quot;<br />
@implementation GVMaclasse<br />
@synthesize nom;<br />
- (void) connect<br />
{<br />
    const char *conninfo;<br />
    PGconn	 *conn;<br />
   <br />
    conninfo = &quot;dbname = postgres&quot;;<br />
    conn = PQconnectdb(conninfo);<br />
}<br />
@end<br />




Et là  misère : Undefined symbols for architecture i386: "_PQconnectdb", referenced from:

XCode ignore la bibliothèque C...

Il existe un framework "PGSQLKit" créé pour uiliser libpq avec XCode mais je voudrais éviter de dépendre d'un framework que je n'ai pas fait, sans compter les droits... Chose très étrange, si j'ajoute ce Framework à  mon projet mais sans l'utiliser, juste ajouté je n'ai plus le bug !!! mon code précédent run sans erreur !!!

Je ne comprend pas ce qu'il se passe... Habitué à  certaine lecture sur le net je précise que je ne sais pas ce qu'est un "flag"...



Je vous remercie beaucoup d'accepter de m'aider, car si j'arrive enfin à  utiliser libpq avec Xcode je suis sauvé !!! SOS

Réponses

  • CeetixCeetix Membre
    mars 2012 modifié #2
    Pour ta première erreur ça vient de ARC qui n'est pas supporté apparemment par la lib.

    Sinon pour ta dernière erreur, tu as indiqué le chemin de ta lin dans search path (Build Setting Panel) ?
  • zoczoc Membre
    mars 2012 modifié #3
    'chaps31' a écrit:


    Premier problème j'ai dû sélectionner LLVM GCC 4.2 sinon...
    <br />
    error: -fobjc-arc is not supported with fragile abi<br />
    



    Je suppose que tu compiles en 32 bits... Par défaut, Xcode 4 génère des projets 64 bits qui utilisent ARC. Hors ARC n'est pas disponible pour les applications 32 bits.


    Autre bug surprenant, Xcode crée tout seul un AppDelegate dans lequel il crée un @property (assign) IBOutlet NSWindow *window; mais sans créer la variable d'instance !!!


    Normal, la variable d'instance n'est plus nécessaire quand on compile en 64 bits (ou pour iOS), le compilateur est capable de la créer tout seul.




    Et là  misère : Undefined symbols for architecture i386: "_PQconnectdb", referenced from:

    XCode ignore la bibliothèque C...


    Tu as bien rajouté le fichier ".a" (ou .dylib) explicitement au projet pour que le linker sache qu'il doit linker avec la librairie ? Parce qu'il ne la trouvera jamais tout seul. Que le compilateur trouve le .h tout seul quand il est inclus est une chose (du moment où il est dans /usr/include ou /usr/local/include c'est normal), mais il ne devinera jamais qu'il doit linker avec une librairie supplémentaire.
  • Merci beaucoup de votre réactivité. Bon j'ai remis en 64 bits uniquement, pour le .a, je l'ai trouvé et je l'ai ajouté et.... 70 erreurs...
    <br />
    Undefined symbols for architecture i386:<br />
      &quot;_krb5_init_context&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
      &quot;_error_message&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
    	  _pg_krb5_sendauth in libpq.a(fe-auth.o)<br />
      &quot;_krb5_cc_default&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
      &quot;_krb5_free_context&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
    	  _pg_krb5_destroy in libpq.a(fe-auth.o)<br />
      &quot;_krb5_cc_get_principal&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
      &quot;_krb5_cc_close&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
    	  _pg_krb5_destroy in libpq.a(fe-auth.o)<br />
      &quot;_krb5_unparse_name&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
      &quot;_krb5_free_principal&quot;, referenced from:<br />
    	  _pg_krb5_init in libpq.a(fe-auth.o)<br />
    	  _pg_krb5_destroy in libpq.a(fe-auth.o)<br />
    	  _pg_krb5_sendauth in libpq.a(fe-auth.o)<br />
      &quot;_krb5_free_unparsed_name&quot;, referenced from:<br />
    	  _pg_krb5_destroy in libpq.a(fe-auth.o)<br />
      &quot;_krb5_sname_to_principal&quot;, referenced from:<br />
    	  _pg_krb5_sendauth in libpq.a(fe-auth.o)<br />
      &quot;_krb5_sendauth&quot;, referenced from:<br />
    	  _pg_krb5_sendauth in libpq.a(fe-auth.o)<br />
      &quot;_krb5_free_error&quot;, referenced from:<br />
    	  _pg_krb5_sendauth in libpq.a(fe-auth.o)<br />
    etc.......<br />
    




    Bigre, bigre... Je sors ma paire de rames et ce qui est fou c'est que si j'ajoute le framework au projet sans l'utiliser tout marche !!! C'est incompréhensible... Je suis preneur de toute idée...

    Sinon pourquoi avec LLVM GCC 4.2 je n'ai plus l'erreur lié à  l'ARC ?



    J'ai l'impression qu'il va falloir que je potasse comment fonctionne une librairie... .a...
  • zoczoc Membre
    'chaps31' a écrit:


    Sinon pourquoi avec LLVM GCC 4.2 je n'ai plus l'erreur lié à  l'ARC ?


    Tout simplement parce que LLVM GCC ne supporte pas ARC, et qu'il est donc désactivé. Pour utiliser ARC, il faut obligatoirement compiler avec Clang.
  • Bon... Mon choix est fait, gérer seul une base postgresql via libpq est une vrai galère donc j'utilise le framework tiers...
  • Bon du coup ça marche beaucoup mieux, dans le framework il y a une classe de connection, qui permet de se connecter avec les paramètres du serveur postgresql à  une base de donnée et de faire tout ce que l'on a à  y faire. Donc j'instancie cette classe et obtient un objet de connexion, ça marche très bien. Je peux faire ça partout où j'ai besoin d'accéder à  la base mais ce n'est pas terrible, j'aurais aimé créer un objet de connexion et me connecter dans applicationDidFinishLaunching:(NSNotification *)aNotification de mon AppDelegate une bonne foispour toute et que cet objet de connexion soit accessible par toutes mes instances de toutes mes classes... Mais je ne vois pas comment cela est possible... Une idée ? Merci.
  • C'est pourtant pas compliqué, il suffit de créer une méthode dans ta classe AppDelegate et celle-ci sera accessible partout dans ton programme avec:



    [[NSApp delegate] maMethode];
  • Oui, oui, mais en fait j'aurais aimé une variable d'instance de mon AppDelegate qui aurait été mon objet de connexion qui persiste pour toute mon appli... En réfléchissant j'ai opté pour une autre solution : vu que la méthode de connexion est toujours la même, que le code pour passer de ce qui sort de ma base via le framework à  un tableau sera toujours le même (seule la requête SQL change) et que les requêtes vont beaucoup se ressembler (lecture écriture sur maximum 5 à  7 tables), je crée une classe sans variable d'instance qui fera tout ça et qui ne contient que des méthodes de classe, un import dans chaque classe où l'accès à  la base m'est indispensable et ce sera bon, l'objet de connexion est recréé par les méthode de cette classe à  chaque fois certes, mais pas d'intanciation directe dans mes autres classes... Je pense que c'est la solution.
  • mpergandmpergand Membre
    avril 2012 modifié #10
    'chaps31' a écrit:


    Oui, oui, mais en fait j'aurais aimé une variable d'instance de mon AppDelegate qui aurait été mon objet de connexion qui persiste pour toute mon appli...




    Ben tu initialises cette variable dans applicationDidFinishLaunching:



    Maintenant encore mieux: tu te crées un PostgresqlManager en singleton dans lequel tu pourras y ajouter toutes les méthodes nécessaires à  la gestion de ta base.
  • Ce fil m'intéresse car toutes mes applications font appel à  PGSQLKit pour accéder à  mes bases Postgresql. J'en suis très content.

    Comme toi j'ai abandonné libpq, trop compliquée à  utiliser au fil des différentes version de Xcode et Cocoa.



    Pour ma part, chaque classe qui a besoin d'accéder aux bases a ses propres variables de connexion. Cela me semblait plus logique.
  • Personnellement je trouve qu'en programmation orientée objet je préfère créer une seule classe de connexion, je ne sais pas si j'ai raison.. Dans cette classe je n'ai que des méthodes de classe, je ne l'instancie pas, peut-être y-at-t'il d'autres moyens plus sioux de faire ça, mais ma classe a une méthode qui renvoie un objet de connexion, une qui renvoie un NSMutableArray et qui reçoit une requête en NSString, puis d'autre qui renvoie des tableaux de données spécifiques issus de la BDD que j'utilise beaucoup (toujours les mêmes).
  • mpergandmpergand Membre
    avril 2012 modifié #13
    'chaps31' a écrit:


    Personnellement je trouve qu'en programmation orientée objet je préfère créer une seule classe de connexion, je ne sais pas si j'ai raison.. Dans cette classe je n'ai que des méthodes de classe, je ne l'instancie pas, peut-être y-at-t'il d'autres moyens plus sioux de faire ça.




    Oui, ça s'appelle un singleton. D'aucuns sur ce forum te diront que les méthodes de classes et les variables statics c'est pas bien, perso j'ai pas de problème avec ça.

    L'avantage fonctionnelle du singleton est subtil, c'est plus facile à  faire évoluer si en veut sous classer ce singleton, mais c'est très rare d'avoir besoin de la faire.

    Mais surtout ne par perdre de vu que l'on ne peut gérer qu'une seule base de données pour tout le programme.

    Perso, j'ai des classes managers pour gérer des BD, mais ce ne sont pas des singletons, une instance est crée pour chaque BD à  gérer.
Connectez-vous ou Inscrivez-vous pour répondre.