Je débute en C++. J'essaye d'écrire un petit programme utilisant CulrPP
et j'ai un probleme avec la classe cURLpp::Types::WriteFunctionFunctor
je la définit comme suit
cURLpp::Types::WriteFunctionFunctor functor(WriteMemoryCallback);
et la fonction WriteMemoryCallback :
size_t WriteMemoryCallback(char* ptr, size_t size, size_t nmemb) {
string strTmp(ptr,size);
buffer += strTmp;
return size*nmemb;
};
Ca fonctionne très bien tant que WriteMemoryCallback est une simple
fonction. Par contre, si je l'encapsule dans une classe, GCC me renvoie :
g++ -Wall -O2 -I/usr/include -c ButineurVirtuel.cpp -o
obj/Release/ButineurVirtuel.o
ButineurVirtuel.cpp: In member function «std::string
ButineurVirtuel::load(std::string)»:
ButineurVirtuel.cpp:22: erreur: no matching function for call to
«utilspp::Functor<unsigned int, utilspp::tl::TypeList<char*,
utilspp::tl::TypeList<unsigned int, utilspp::tl::TypeList<unsigned int,
utilspp::NullType> > > >::Functor(<unknown type>)»
/usr/local/include/utilspp/functor/Functor.inl:29: note: candidats sont:
utilspp::Functor<R, TList>::Functor(Fun) [with Fun = size_t
(ButineurVirtuel::*)(char*, size_t, size_t), R = unsigned int, TList =
utilspp::tl::TypeList<char*, utilspp::tl::TypeList<unsigned int,
utilspp::tl::TypeList<unsigned int, utilspp::NullType> > >]
/usr/local/include/utilspp/functor/Functor.inl:40: note:
utilspp::Functor<R, TList>::Functor(const utilspp::Functor<R, TList>&)
[with R = unsigned int, TList = utilspp::tl::TypeList<char*,
utilspp::tl::TypeList<unsigned int, utilspp::tl::TypeList<unsigned int,
utilspp::NullType> > >]
Process terminated with status 1 (0 minutes, 7 seconds)
3 errors, 0 warnings
D'avance merci,
TSalm
Les codes complets: Le premier listing fonctionne, l'autre non:
=========================DEBUT=============================
#include "main.h"
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>
// Das writer-Callback setzten, damit
// cURL in einen std::string schreibt
cURLpp::Types::WriteFunctionFunctor functor(WriteMemoryCallback);
cURLpp::Options::WriteFunction *test = new
cURLpp::Options::WriteFunction(functor);
request.setOpt(test);
// Die URL setzten, die emfangen werden soll
request.setOpt(new cURLpp::Options::Url(url));
request.setOpt(new cURLpp::Options::Verbose(false));
request.perform();
en effet, "l'encapsulation" dans une classe change la visibilité.
None seulement la visibilité. Une fonction membre non statique a un paramètre de plus, le pointeur this. Et il faut l'appeler avec une syntaxe différente, avec un object.
on pouvait supposer que 'none' sait ce qu'est une méthode d'instance vs de classe.
une callback doit être static.
Typiquement, il faut aussi qu'elle soit « extern "C" », ce qui exclut des fonctions membres statiques aussi. Il faut qu'elle soit globale.
pourquoi "typiquement" ? a) le pb n'est pas posé ici comme lié à un déploiement par librairies (ok, le contraire (application monolithique) n'est pas affirmé) b) avec, par exemple, les extensions MS, je peux importer la définition:
et utiliser un ButineurVirtuel::WriteMemoryCallback(...) correctement manglé (décoré); gcc ne sait pas publier une classe ? (j'aurais pensé que comme pour les globales, tout est exporté).
Sylvain.
James Kanze wrote on 07/10/2006 18:25:
en effet, "l'encapsulation" dans une classe change la visibilité.
None seulement la visibilité. Une fonction membre non statique a
un paramètre de plus, le pointeur this. Et il faut l'appeler
avec une syntaxe différente, avec un object.
on pouvait supposer que 'none' sait ce qu'est une méthode d'instance vs
de classe.
une callback doit être static.
Typiquement, il faut aussi qu'elle soit « extern "C" », ce qui
exclut des fonctions membres statiques aussi. Il faut qu'elle
soit globale.
pourquoi "typiquement" ?
a) le pb n'est pas posé ici comme lié à un déploiement par librairies
(ok, le contraire (application monolithique) n'est pas affirmé)
b) avec, par exemple, les extensions MS, je peux importer la définition:
et utiliser un ButineurVirtuel::WriteMemoryCallback(...) correctement
manglé (décoré); gcc ne sait pas publier une classe ? (j'aurais pensé
que comme pour les globales, tout est exporté).
en effet, "l'encapsulation" dans une classe change la visibilité.
None seulement la visibilité. Une fonction membre non statique a un paramètre de plus, le pointeur this. Et il faut l'appeler avec une syntaxe différente, avec un object.
on pouvait supposer que 'none' sait ce qu'est une méthode d'instance vs de classe.
une callback doit être static.
Typiquement, il faut aussi qu'elle soit « extern "C" », ce qui exclut des fonctions membres statiques aussi. Il faut qu'elle soit globale.
pourquoi "typiquement" ? a) le pb n'est pas posé ici comme lié à un déploiement par librairies (ok, le contraire (application monolithique) n'est pas affirmé) b) avec, par exemple, les extensions MS, je peux importer la définition:
et utiliser un ButineurVirtuel::WriteMemoryCallback(...) correctement manglé (décoré); gcc ne sait pas publier une classe ? (j'aurais pensé que comme pour les globales, tout est exporté).
Sylvain.
kanze
Sylvain wrote:
James Kanze wrote on 07/10/2006 18:25:
en effet, "l'encapsulation" dans une classe change la visibilité.
None seulement la visibilité. Une fonction membre non statique a un paramètre de plus, le pointeur this. Et il faut l'appeler avec une syntaxe différente, avec un object.
on pouvait supposer que 'none' sait ce qu'est une méthode d'instance vs de classe.
Tout à fait. Et qu'il sait même quelle classe, et qu'il en a une instance.
Arrivé là, on peut dire qu'on a une interface C++, et non une interface C. Et dans une interface C++, c'est peut probable qu'on démande l'adresse d'une fonction ; on spécifie une classe abstraite, avec une fonction virtuelle qu'on appelle.
une callback doit être static.
Typiquement, il faut aussi qu'elle soit « extern "C" », ce qui exclut des fonctions membres statiques aussi. Il faut qu'elle soit globale.
pourquoi "typiquement" ?
Parce que la plupart des API sont définies en termes de C. Et celle qui sont définies en termes de C++ ne prenent pas de pointeurs à des fonctions, parce qu'un pointeur à une classe abstraite résoud le problème d'une façon bien meilleur.
a) le pb n'est pas posé ici comme lié à un déploiement par librai ries (ok, le contraire (application monolithique) n'est pas affirmé) b) avec, par exemple, les extensions MS, je peux importer la définition:
et utiliser un ButineurVirtuel::WriteMemoryCallback(...) correctement manglé (décoré); gcc ne sait pas publier une classe ? (j'aurais pensé que comme pour les globales, tout est exporté).
Je ne comprends rien de tout celà. Ce n'est pas du C++.
C'est certain qu'une implémentation peut offrir des extensions pour supporter différents cas. Si on se sert d'une bibliothèque qui exige l'utilisation des extensions, il faut y passer. Mais c'est un cas un peu exceptionnel, ou au moins, je l'espère ; du moment qu'on se sert des telles extensions, on est coincé, on dépend entièrement de leur fournisseur.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sylvain wrote:
James Kanze wrote on 07/10/2006 18:25:
en effet, "l'encapsulation" dans une classe change la visibilité.
None seulement la visibilité. Une fonction membre non
statique a un paramètre de plus, le pointeur this. Et il
faut l'appeler avec une syntaxe différente, avec un object.
on pouvait supposer que 'none' sait ce qu'est une méthode
d'instance vs de classe.
Tout à fait. Et qu'il sait même quelle classe, et qu'il en a une
instance.
Arrivé là, on peut dire qu'on a une interface C++, et non une
interface C. Et dans une interface C++, c'est peut probable
qu'on démande l'adresse d'une fonction ; on spécifie une classe
abstraite, avec une fonction virtuelle qu'on appelle.
une callback doit être static.
Typiquement, il faut aussi qu'elle soit « extern "C" », ce qui
exclut des fonctions membres statiques aussi. Il faut qu'elle
soit globale.
pourquoi "typiquement" ?
Parce que la plupart des API sont définies en termes de C. Et
celle qui sont définies en termes de C++ ne prenent pas de
pointeurs à des fonctions, parce qu'un pointeur à une classe
abstraite résoud le problème d'une façon bien meilleur.
a) le pb n'est pas posé ici comme lié à un déploiement par librai ries
(ok, le contraire (application monolithique) n'est pas affirmé)
b) avec, par exemple, les extensions MS, je peux importer la définition:
et utiliser un ButineurVirtuel::WriteMemoryCallback(...)
correctement manglé (décoré); gcc ne sait pas publier une
classe ? (j'aurais pensé que comme pour les globales, tout est
exporté).
Je ne comprends rien de tout celà. Ce n'est pas du C++.
C'est certain qu'une implémentation peut offrir des extensions
pour supporter différents cas. Si on se sert d'une bibliothèque
qui exige l'utilisation des extensions, il faut y passer. Mais
c'est un cas un peu exceptionnel, ou au moins, je l'espère ; du
moment qu'on se sert des telles extensions, on est coincé, on
dépend entièrement de leur fournisseur.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
en effet, "l'encapsulation" dans une classe change la visibilité.
None seulement la visibilité. Une fonction membre non statique a un paramètre de plus, le pointeur this. Et il faut l'appeler avec une syntaxe différente, avec un object.
on pouvait supposer que 'none' sait ce qu'est une méthode d'instance vs de classe.
Tout à fait. Et qu'il sait même quelle classe, et qu'il en a une instance.
Arrivé là, on peut dire qu'on a une interface C++, et non une interface C. Et dans une interface C++, c'est peut probable qu'on démande l'adresse d'une fonction ; on spécifie une classe abstraite, avec une fonction virtuelle qu'on appelle.
une callback doit être static.
Typiquement, il faut aussi qu'elle soit « extern "C" », ce qui exclut des fonctions membres statiques aussi. Il faut qu'elle soit globale.
pourquoi "typiquement" ?
Parce que la plupart des API sont définies en termes de C. Et celle qui sont définies en termes de C++ ne prenent pas de pointeurs à des fonctions, parce qu'un pointeur à une classe abstraite résoud le problème d'une façon bien meilleur.
a) le pb n'est pas posé ici comme lié à un déploiement par librai ries (ok, le contraire (application monolithique) n'est pas affirmé) b) avec, par exemple, les extensions MS, je peux importer la définition:
et utiliser un ButineurVirtuel::WriteMemoryCallback(...) correctement manglé (décoré); gcc ne sait pas publier une classe ? (j'aurais pensé que comme pour les globales, tout est exporté).
Je ne comprends rien de tout celà. Ce n'est pas du C++.
C'est certain qu'une implémentation peut offrir des extensions pour supporter différents cas. Si on se sert d'une bibliothèque qui exige l'utilisation des extensions, il faut y passer. Mais c'est un cas un peu exceptionnel, ou au moins, je l'espère ; du moment qu'on se sert des telles extensions, on est coincé, on dépend entièrement de leur fournisseur.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sylvain
kanze wrote on 11/10/2006 09:36:
[...] Et dans une interface C++, c'est peut probable qu'on demande l'adresse d'une fonction ; on spécifie une classe abstraite, avec une fonction virtuelle qu'on appelle.
je privilégie tjrs les modèles basés sur un polymorphisme ... mais ce n'est pas l'unique solution et il arrive que l'on préfère une autre approche.
c'est, IHMO, le cas, lorsqu'une "classe container" doit appliquer des traitements (sort, for each, first that, ...) sur les éléments, on peut alors souhaiter définir ces traitements comme static de la classe élement plutôt que comme globales.
soit, le tri peut se faire via un "int T.relativeOrder(T& other)" d'une interface sortable idoine; soit, les itérations peuvent être autant de méthodes du container (chacune invoquant une virtuelle donnée); toutefois on peut préférer ne pas (ou être empêcher de) définir toutes ces virtuelles mais plutôt une callback static quand il y a lieu.
Parce que la plupart des API sont définies en termes de C. Et celle qui sont définies en termes de C++ ne prenent pas de pointeurs à des fonctions, parce qu'un pointeur à une classe abstraite résoud le problème d'une façon bien meilleur.
c'est plus ou moins le même point, non ? je suis d'accord que la façon est "meilleure" d'un point de vue ""académique"", elle peut être un peu lourde en pratique.
C'est certain qu'une implémentation peut offrir des extensions pour supporter différents cas. Si on se sert d'une bibliothèque qui exige l'utilisation des extensions, il faut y passer. Mais c'est un cas un peu exceptionnel, ou au moins, je l'espère ; du moment qu'on se sert des telles extensions, on est coincé, on dépend entièrement de leur fournisseur.
l'exemple que j'ai donné adressait le problème d'une static (non globale) dans une librairie *externe* - c'est un cas qui ne me parait pas fréquent voire pas judicieux.
Sylvain.
kanze wrote on 11/10/2006 09:36:
[...] Et dans une interface C++, c'est peut probable
qu'on demande l'adresse d'une fonction ; on spécifie une classe
abstraite, avec une fonction virtuelle qu'on appelle.
je privilégie tjrs les modèles basés sur un polymorphisme ... mais ce
n'est pas l'unique solution et il arrive que l'on préfère une autre
approche.
c'est, IHMO, le cas, lorsqu'une "classe container" doit appliquer des
traitements (sort, for each, first that, ...) sur les éléments, on peut
alors souhaiter définir ces traitements comme static de la classe
élement plutôt que comme globales.
soit, le tri peut se faire via un "int T.relativeOrder(T& other)" d'une
interface sortable idoine; soit, les itérations peuvent être autant de
méthodes du container (chacune invoquant une virtuelle donnée);
toutefois on peut préférer ne pas (ou être empêcher de) définir toutes
ces virtuelles mais plutôt une callback static quand il y a lieu.
Parce que la plupart des API sont définies en termes de C. Et
celle qui sont définies en termes de C++ ne prenent pas de
pointeurs à des fonctions, parce qu'un pointeur à une classe
abstraite résoud le problème d'une façon bien meilleur.
c'est plus ou moins le même point, non ?
je suis d'accord que la façon est "meilleure" d'un point de vue
""académique"", elle peut être un peu lourde en pratique.
C'est certain qu'une implémentation peut offrir des extensions
pour supporter différents cas. Si on se sert d'une bibliothèque
qui exige l'utilisation des extensions, il faut y passer. Mais
c'est un cas un peu exceptionnel, ou au moins, je l'espère ; du
moment qu'on se sert des telles extensions, on est coincé, on
dépend entièrement de leur fournisseur.
l'exemple que j'ai donné adressait le problème d'une static (non
globale) dans une librairie *externe* - c'est un cas qui ne me parait
pas fréquent voire pas judicieux.
[...] Et dans une interface C++, c'est peut probable qu'on demande l'adresse d'une fonction ; on spécifie une classe abstraite, avec une fonction virtuelle qu'on appelle.
je privilégie tjrs les modèles basés sur un polymorphisme ... mais ce n'est pas l'unique solution et il arrive que l'on préfère une autre approche.
c'est, IHMO, le cas, lorsqu'une "classe container" doit appliquer des traitements (sort, for each, first that, ...) sur les éléments, on peut alors souhaiter définir ces traitements comme static de la classe élement plutôt que comme globales.
soit, le tri peut se faire via un "int T.relativeOrder(T& other)" d'une interface sortable idoine; soit, les itérations peuvent être autant de méthodes du container (chacune invoquant une virtuelle donnée); toutefois on peut préférer ne pas (ou être empêcher de) définir toutes ces virtuelles mais plutôt une callback static quand il y a lieu.
Parce que la plupart des API sont définies en termes de C. Et celle qui sont définies en termes de C++ ne prenent pas de pointeurs à des fonctions, parce qu'un pointeur à une classe abstraite résoud le problème d'une façon bien meilleur.
c'est plus ou moins le même point, non ? je suis d'accord que la façon est "meilleure" d'un point de vue ""académique"", elle peut être un peu lourde en pratique.
C'est certain qu'une implémentation peut offrir des extensions pour supporter différents cas. Si on se sert d'une bibliothèque qui exige l'utilisation des extensions, il faut y passer. Mais c'est un cas un peu exceptionnel, ou au moins, je l'espère ; du moment qu'on se sert des telles extensions, on est coincé, on dépend entièrement de leur fournisseur.
l'exemple que j'ai donné adressait le problème d'une static (non globale) dans une librairie *externe* - c'est un cas qui ne me parait pas fréquent voire pas judicieux.
Sylvain.
James Kanze
Manuel Zaccaria wrote:
"kanze" a écrit:
[...]
Mieux, je ne sais pas. Mais celle de Boost a quelques problèmes sérieux, comme le fait qu'une exception non-catchée puisse rendre un thread détaché. Elle ne permet pas non plus la propagation d'une exception à travers un join.
Le mécanisme RTTI est malheureusement insuffisant pour propager une exception d'un thread à un autre (j'ai essayé... j'ai peut-être raté un truc, BTW).
Si c'est toi qui gère l'hièrarchie des exceptions, c'est faisable, au moyen d'un peu de travail, mais ce n'est pas évident. Si ce n'est pas toi qui la gère, en revanche, il n'y a pas de moyen.
Si seulement le C++ supportait l'introspection, ça résoudrait bien des problèmes, surtout pour la sérialisation.
J'ai mes doutes en ce qui concerne la sérialisation. Ça n'aide que peu en Java, malgré ce qu'on dit. Mais c'est vrai que pour la transmission des exceptions, elle serait bien utile.
Note que les mechanismes nécessaires sont au moins en partie présente, parce que nécessaire de toute façon pour la gestion des exceptions.
-- James Kanze Gabi Software email: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Manuel Zaccaria wrote:
"kanze" a écrit:
[...]
Mieux, je ne sais pas. Mais celle de Boost a quelques problèmes
sérieux, comme le fait qu'une exception non-catchée puisse
rendre un thread détaché. Elle ne permet pas non plus la
propagation d'une exception à travers un join.
Le mécanisme RTTI est malheureusement insuffisant pour propager
une exception d'un thread à un autre (j'ai essayé... j'ai peut-être
raté un truc, BTW).
Si c'est toi qui gère l'hièrarchie des exceptions, c'est
faisable, au moyen d'un peu de travail, mais ce n'est pas
évident. Si ce n'est pas toi qui la gère, en revanche, il n'y a
pas de moyen.
Si seulement le C++ supportait l'introspection, ça résoudrait
bien des problèmes, surtout pour la sérialisation.
J'ai mes doutes en ce qui concerne la sérialisation. Ça n'aide
que peu en Java, malgré ce qu'on dit. Mais c'est vrai que pour
la transmission des exceptions, elle serait bien utile.
Note que les mechanismes nécessaires sont au moins en partie
présente, parce que nécessaire de toute façon pour la gestion
des exceptions.
--
James Kanze Gabi Software email: kanze.james@neuf.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Mieux, je ne sais pas. Mais celle de Boost a quelques problèmes sérieux, comme le fait qu'une exception non-catchée puisse rendre un thread détaché. Elle ne permet pas non plus la propagation d'une exception à travers un join.
Le mécanisme RTTI est malheureusement insuffisant pour propager une exception d'un thread à un autre (j'ai essayé... j'ai peut-être raté un truc, BTW).
Si c'est toi qui gère l'hièrarchie des exceptions, c'est faisable, au moyen d'un peu de travail, mais ce n'est pas évident. Si ce n'est pas toi qui la gère, en revanche, il n'y a pas de moyen.
Si seulement le C++ supportait l'introspection, ça résoudrait bien des problèmes, surtout pour la sérialisation.
J'ai mes doutes en ce qui concerne la sérialisation. Ça n'aide que peu en Java, malgré ce qu'on dit. Mais c'est vrai que pour la transmission des exceptions, elle serait bien utile.
Note que les mechanismes nécessaires sont au moins en partie présente, parce que nécessaire de toute façon pour la gestion des exceptions.
-- James Kanze Gabi Software email: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34