IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

Références indéfinies avec bind


Sujet :

Boost C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 132
    Points : 89
    Points
    89
    Par défaut Références indéfinies avec bind
    Bonjour,
    J'ai un léger soucis à la compilation avec Boost, concernant boost::bind, dont je n'arrive pas à trouver la cause.

    Voici le rapport de compilation (incomplet, mais le reste ne comporte ni warnings, ni erreurs, ...) :
    Citation Envoyé par CMake
    [ 15%] Built target ScheduleEngine
    Scanning dependencies of target NetworkEngine
    [ 19%] Building CXX object CommunicationClients/CMakeFiles/NetworkEngine.dir/tcp_sock.cpp.o
    Linking CXX shared library ../libNetworkEngine.so
    [ 34%] Built target NetworkEngine
    [ 38%] Built target DbEngine
    Linking CXX executable server.bin
    ./libNetworkEngine.so: undefined reference to `void TcpSock::async_write<EngineEvent, boost::_bi::bind_t<void, boost::_mfi::mf1<void, NetworkMachine, boost::system::error_code>, boost::_bi::list2<boost::_bi::valu
    ost::_bi::bind_t<void, boost::_mfi::mf1<void, NetworkMachine, boost::system::error_code>, boost::_bi::list2<boost::_bi::value<NetworkMachine*>, boost::arg<1> (*)()> >)'
    ./libNetworkEngine.so: undefined reference to `void TcpSock::async_read<EngineEvent, boost::_bi::bind_t<void, boost::_mfi::mf2<void, NetworkMachine, EngineEvent, boost::system::error_code>, boost::_bi::list3<boos
    st::arg<1> (*)()> > >(EngineEvent&, boost::_bi::bind_t<void, boost::_mfi::mf2<void, NetworkMachine, EngineEvent, boost::system::error_code>, boost::_bi::list3<boost::_bi::value<NetworkMachine*>, boost::_bi::value
    collect2: ld a retourné 1 code d'état d'exécution
    make[2]: *** [server.bin] Erreur 1
    make[1]: *** [CMakeFiles/server.bin.dir/all] Erreur 2
    make: *** [all] Erreur 2


    Dans la classe TcpSock, j'ai bel et bien les fonctions async_write et async_read, publiques et tout et tout... Les voilà :

    async_write :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
     * send serializable object
     *\param t event to send
     */
    template <typename T, typename Handler>
    void TcpSock::async_write(const T& t, Handler handler) {
    	std::ostringstream archiveStream;
    	boost::archive::text_oarchive archive(archiveStream);
        archive << t;
    	const std::string &outboundData = archiveStream.str();
     
    	boost::system::error_code error;
    	m_sock->write_some(boost::asio::buffer(outboundData), error);
     
    	if (error)
    		boost::bind(handler, error);
    }
    Et async_read :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
     * sets a callback called when a T is received
     *\param t T to receive
     *\param handler callback
     */
    template <typename T, typename Handler>
    void TcpSock::async_read(T& t, Handler handler) {
    	void (TcpSock::*f)(const boost::system::error_code&, T&, boost::tuple<Handler>) = &TcpSock::handle_read<T, Handler>;
    	boost::asio::async_read(m_sock, boost::asio::buffer(m_networkBuffer),
    		boost::bind(f,
    			this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, boost::ref(t), boost::make_tuple(handler)));
    }
    La fonction handle_read, déclarée private, elle (ce n'est pas la source de l'erreur, vu qu'elle n'est pas utilisée par async_write, qui me pose problème aussi), est la suivante, au cas où... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    template <typename T, typename Handler>
    void TcpSock::handle_read(const boost::system::error_code& e, size_t pBytesReceived, T& t, boost::tuple<Handler> handler) {
    	if (e) {
    		boost::get<0>(handler)(t, e);
    	}
    	else {
    		try {
    			std::string strData(&m_networkBuffer[0], pBytesReceived);
    			std::istringstream archiveStream(strData);
    			boost::archive::text_iarchive archive(archiveStream);
    			archive >> t;
    		} catch (std::exception& e) {
    			// En cas d'échec
    			boost::system::error_code error(boost::asio::error::invalid_argument);
    			boost::get<0>(handler)(t, error);
    			return;
    		}
     
    		// On informe l'appelant que tout s'est bien passé.
    		boost::get<0>(handler)(t, e);
    	}
    }
    Ces fonctions (async_read et async_write) sont utilisées de la manière suivante :

    async_write :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /**
     * send event via tcp to this machine
     *\param pE event to send
     */
    void NetworkMachine::tcpSend(const EngineEvent& pE) {
    	m_tcpSock->async_write(pE, boost::bind(&NetworkMachine::handleWrite, this,
    		boost::asio::placeholders::error));
    }
    (Où m_tcpSock est un TcpSock*)

    async_read :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /** 
     * massively used constructor
     *\param pP pointor to parent
     *\param pSo tcp socket attached to this network machine
     *\param pI id for this network machine
     *\param pAcctName name of the account linked with the machine
     */
    NetworkMachine::NetworkMachine(NetworkEngine* pP, boost::asio::ip::tcp::socket *pSo, int pI, std::string pAcctName) : m_parent(pP), m_id(pI), m_acctName(pAcctName) {
    	m_tcpSock = new TcpSock(pSo);
    	// (...)
    	// set up the async reading
    	EngineEvent e;
    	m_tcpSock->async_read(e, boost::bind(&NetworkMachine::handleRead, this, e,
    		boost::asio::placeholders::error));
    }

    Voili voilà, ça fait quelques heures que je sèche là dessus, j'ai beau chercher, je trouve rien... Si quelqu'un a la moindre piste, je suis preneur.
    Merci

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 132
    Points : 89
    Points
    89
    Par défaut
    J'ai un p'tit peu (vraiment un tout p'tit peu…) avancé : Dans la fonction NetworkMachine::tcpSend, si je n'utilise pas le m_tcpSock->async_write, je n'ai pas de référence indéfinie, ça compile… (du moins, pour la référence indéfinie sur async_write, mais j'ai la même chose si je commente la ligne qui utilise async_read)

    Ce que je pige vraiment pas, c'est que la librairie NetworkEngine, qui contient NetworkMachine, TcpSock, et NetworkEngine (qui ne pose pas de soucis), se compile très bien, et que je ne fais aucun appel direct à NetworkMachine ou TcpSock depuis server.bin :/

    Edit : Je suis en train de devenir dingue… Le contenu de NetworkMachine::tcpSend, copié exactement (en remplacant m_tcpSock par this), dans le constructeur de TcpSock, ne pose aucun soucis… C'est pourtant pas un problème d'include…

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Les définitions des fonctions templates doivent se trouver dans les fichiers d'entête (.hpp).
    Est-ce bien le cas ?

Discussions similaires

  1. Réponses: 10
    Dernier message: 02/01/2007, 13h07
  2. [Linker MinGW]Références indéfinies mais libs incluses
    Par oiffrig dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 31/08/2006, 14h35
  3. Gestion facilitée de serveurs DNS avec bind
    Par marcha dans le forum Réseau
    Réponses: 1
    Dernier message: 17/08/2006, 16h15
  4. Problème avec bind!!!
    Par ouakammathieu dans le forum Réseau
    Réponses: 4
    Dernier message: 15/05/2006, 00h46
  5. Problème avec bind
    Par jaabouc dans le forum Réseau
    Réponses: 5
    Dernier message: 12/06/2005, 15h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo