[résolu]xcode c++ "void funct ()()();"

mybofymybofy Membre
août 2015 modifié dans Xcode et Developer Tools #1

Bonjour


Yosemite - Xcode 6 - wxWidgets 3 - PostgreSQL 9.3 - libpqxx 4


 


Mon application est écrite en C++ (utilisation de wxWidgets en vue de portage ...) .


 


Donc il m'a semblé cohérent d'utiliser l'inteface C++ (libpqxx) pour la gestion de ma base PG.


 


J'ai un peu de mal !


 


Je veux utiliser la classe (?) "prepare" de libpqxx.


J'ai trouvé http://stackoverflow.com/questions/16047986/how-to-insert-binary-data-into-a-postgresql-bytea-column-using-the-c-libpqxx-a qui semble répondre à  mon objectif


 


L'instruction (structure) qui m'intéresse :



string prepName = "essai0"
reqSqlWithParms = "select * from $1";
string typeSql = "varchar";
connection *conn;
conn->prepare(prepName, reqSqlWithParms) (typeSql, treat_string);
^

Message d'erreur Xcode :


Called object type 'void' is not a function or function pointer


 


D'après ce que j'ai compris le bloc en erreur sert à  définir le type du paramètre $1. C'est une syntaxe pas absurde à  priori (rappelle un peu l'appel des paramètres d'une méthode de l'ObjC), syntaxe que je ne connais pas, mais que le compilateur standard avec la librairie standard associée ne connaà®t pas lui non plus.


 


Si je supprime ce bloc en conservant le paramère "$1", j'ai une autre erreur assez logique :


ERROR:  syntax error at or near "$1"


LINE 1: select * from $1;


 


J'ai vu cette syntaxe à  plusieurs reprises pour la classe "prépare", mais la doc de libpqxx que j'utilise ne le prévoit pas. D'ailleurs Xcode ne la propose pas dans la complétion automatique.


 


Lorsque je supprime le paramètre "$1" et le bloc qui le définit, tout se passe bien...


 


Quelqu'un aurait-il une idée ?


Merci.


Réponses

  • zoczoc Membre
    août 2015 modifié #2


    L'instruction (structure) qui m'intéresse :



    string prepName = "essai0"
    reqSqlWithParms = "select * from $1";
    string typeSql = "varchar";
    connection *conn;
    conn->prepare(prepName, reqSqlWithParms) (typeSql, treat_string);
    ^

    Message d'erreur Xcode :


    Called object type 'void' is not a function or function pointer


     




     


    Premier problème, le type de reqSqlWithParms n'est pas défini. Le compilateur ne peut pas le deviner.


     


    Ensuite, prepare c'est pas une class, mais une méthode de la classe connection. Le code ci-dessus va planter à  coup sur, puisqu'il appelle la méthode prépare sur un object de type connection (pointeur conn) qui n'a jamais été créé.


     


    Enfin, les appels de méthodes en C++ sont syntaxiquement identiques à  des appels de fonction en C. Donc ce qui est écrit ici ne peut fonctionner que si la méthode prepare retourne un pointeur sur fonction prenant 2 paramètres (et encore je ne suis pas certain que ca fonctionne tel quel à  cause de la précédence des opérateurs) ou un objet surchargeant l'opérateur () (Parce que oui, en C++ on peut surcharger l'opérateur d'appel de méthodes...).


     


    Ce qui n'est manifestement pas le cas puisque prepare semble retourner void (qui, comme en C, ne veut dire retourne rien).


     


    En l'occurrence, dans les exemples de StackOverflow, c'est la méthode prepared qui est appelée avec cette syntaxe, pas prepare (et je suis presque certain qu'elle retourne un objet surchargeant () ).


     


     


    Conclusion : Ce code ressemble à  tout sauf à  du C++ valide  xd


     


     


    Edit : Finalement, le C++ c'est très bien pour écrire du code illisible pour le néophite...


  • Premier problème : simple oubli d'écriture, il manque le type "string".


     


    Dans les exemples de StackOverflow : c'est bien prepare dans le dernier cas et pas prépared (cf  STORING AN wxImage IN DATABASE).


     


    Bon, ça ne change pas grand chose.


     


    Mais il semble bien qu'il s'agisse de code valide.


     


    Tes réflexions m'ont amené à  plonger dans le monde du C++ : Le langage C++ de Bjorn Stroustrup. Il y a quelque chose qui existe au chapitre 11 "Surcharge des opérateurs", 11.9 "Appel de fonctions", page 319.


     


    Dans la doc de pqxx sur "pqxx::prepare::declaration Class Reference"



    Constructor & Destructor Documentation

    pqxx::prepare::declaration::declaration (connection_base & home, const PGSTD::string &statement)

    Member Function Documentation

    const pqxx::prepare::declaration &pqxx::prepare::declaration::operator()(const PGSTD::string & sqltype, param_treatment treatment = treat_direct) const
    Add a parameter specification to prepared statement declaration. 

    Il n'y a pas de namespace "declaration"


     


     


    Dans pqxx/prepared_statement.hxx :



    00033 namespace prepare
    00034 {
    00036
    00045 enum param_treatment
    00046 {
    00048 treat_binary,
    00050 treat_string,
    00052 treat_bool,
    00054 treat_direct
    00055 };
    00059
    00067 class PQXX_LIBEXPORT declaration
    00068 {
    00069 public:
    00070 declaration(connection_base &, const PGSTD::string &statement);
    00071
    00073 const declaration &
    00074 operator()(const PGSTD::string &sqltype, param_treatment=treat_direct) const;
    00075
    00076 private:
    00078 declaration &operator=(const declaration &);
    00079
    00080 connection_base &m_home;
    00081 const PGSTD::string m_statement;
    00082 };
    00083


    Je n'y comprend pas grand chose.


     


    Voici ce que je devine : il faut remplacer "declaration" par "prepare"


    Dans le cas du constructeur, ça marche...


    Pour le membre qui est apparemment ce qu'il me faut, je ne vois pas quelle syntaxe utiliser ? Ce qui me gêne c'est "const declaration &" : "declaration" me semble faire double emploi avec "operator".


     


    NB :


    1 - Si je fais un bête :


            work pgWork0(*pgConn0);


            const string sql0 = "select * from plante;";


            result pgResult0 = pgWork0.exec(sql0);


    ça marche OK;

    Mais l'idée d'avoir un ensemble de statements préparés que je peux exécuter en leur passant les paramètres adhoc est intéressante, plutôt que de bidouiller le sql0...

    2 - Le C++ est peut être aussi très bien pour écrire du code illisible pour le confirmé...

    Je m'y suis mis  pour tenter de rendre mon code portable... Il faudra après le passer sur Windows et Linux : pas mal de galère en perspective, si du moins j'y arrive.

    Mais que l'écriture de l'application en Objective C était simple (une fois les bases acquises), surtout robuste et permettant un code parfaitement structuré : une classe, deux fichiers.

    Quel horreur que le C++ qui accepte un seul fichier cpp de dizaines de milliers de lignes.

     

    Merci de ta réponse.
  • zoczoc Membre


     


    Quel horreur que le C++ qui accepte un seul fichier cpp de dizaines de milliers de lignes.


     



     


    Ce qui est totalement faux. L'organisation des fichiers sources en C++ est totalement identique à  celle d'Objective-C, pour la simple raison que les 2 langages sont basés sur C et reprennent les mêmes concepts de fichier entête (.h, ou parfois .hxx, voir .hpp en C++ mais c'est rare) et fichier(s) source(s) (.m pour Objective-C, .cpp pour C++).



    const declaration &
    operator()(const PGSTD::string &sqltype, param_treatment=treat_direct) const;

    Le code ci-dessus déclare un opérateur "()" sur un objet de type "declaration" (car membre de cette classe) qui prend 2 paramètres de type "const PGSTD::string &" et "param_treatment" (dont un optionnel), et qui retourne un "const declaration &"


     


    C'est, comme je le supposais dés le départ, ce qui permet de chainer des appels ()()()... et résulte en une syntaxe complètement indigeste à  mon gout.


     


    Après, je ne connais pas du tout libpqxx, donc je ne vais pouvoir aller bien plus loin. Je n'ai pas le temps non plus de donner des cours de C++, parce que le problème est bien là , la méconnaissance du langage.

  • Bon, je laisse tomber "prepare".


     


    Oui, je ne connais pas le langage.


     


    Je ne connaissait pas l'Objective C. Il m'a fallu quelques semaines pour y entrer. Et au fil de l'écriture du code, j'ai réussi à  obtenir ce que je voulais, avec l'aide de CocoaCafé et avec les recherches sur Google.


     


    Merci d'avoir pris de ton temps pour m'éclairer. 


Connectez-vous ou Inscrivez-vous pour répondre.