This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: missing symbols with bobcat C++ library on armel


Dear Ian Lance Taylor, you wrote:
> 
> George Danchev <danchev@spnet.net> writes:
> 
> > Missing symbols are probably related to the following usage pattern (all valid 
> > code in my opinion) of members:
> > MultiStreambuf::overflow(int c)
> > MultiStreambuf::sync()
> > MultiStreambuf::xsputn(char const *buffer, std::streamsize n)
> >
> > * all are private virtual;
> > * all implemented in separate translation unit (multistreambuf.ih);
> > * all inlined
> > * dtor for MultiStreambuf class is not explicitly defined.
> 
> You don't mention it, but the log shows undefined references to the
> vtable for FBB:MultiStreambuf.  I have not looked at the code, but this
> certainly sounds like a missing key method.  Can you show us just the
> declaration of MultiStreambuf from the .h file?  That will let us tell
> you what the key method is.  If that key method is not defined anywhere,
> then these kinds of errors are possible.


Thanks for your reaction to George's questions. 

If you want to have a look at MultiStreambuf's header file, here it is:

-------------------------------------------------------
#ifndef INCLUDED_BOBCAT_MULTISTREAMBUF_
#define INCLUDED_BOBCAT_MULTISTREAMBUF_

#include <cstdio>
#include <streambuf>
#include <vector>
#include <ostream>
#include <string>

namespace FBB
{

class MultiStreambuf: public std::streambuf
{
    public:
        enum Mode
        {
            OFF,                // stream not used
            ON,                 // stream always used
            ONCE,               // stream used until flushed
            RESET,              // stream once used. Set to ONCE to re-use
        };

        class stream            // holds a pointer to a stream and a indicator
        {                       // telling us whether or not to use the stream
            friend class MultiStreambuf;

            std::ostream *d_os;
            Mode          d_mode;

            public:
                stream(std::ostream &os, Mode mode = ON);
                void setMode(Mode mode);
                Mode mode() const;
                std::ostream &ostream();
            private:
                static void setOnce(stream &os);
        };

        typedef std::vector<stream>::iterator iterator;
        typedef std::vector<stream>::const_iterator const_iterator;

    private:
        std::string d_buffer;
        std::vector<stream> d_os;

    public:
        MultiStreambuf() = default;
        explicit MultiStreambuf(std::ostream &os, Mode mode = ON);
        explicit MultiStreambuf(std::vector<stream> const &osvector);

        void insert(std::ostream &os, Mode mode = ON);
        void insert(std::vector<stream> const &os);
        iterator begin();
        iterator end();
        const_iterator begin() const;
        const_iterator end() const;
        void setOnce();             // reset all `RESET' modes to `ONCE'
        
    protected:
        int pSync();

    private:
        virtual int overflow(int c);
        virtual std::streamsize xsputn(char const *buffer, std::streamsize n);
        virtual int sync();

        struct Insert
        {
            std::string &buffer;
            bool ok;
        };
        static void insertStruct(stream &os, Insert &insert); 
};

inline MultiStreambuf::stream::stream(std::ostream &os, Mode mode)
:
    d_os(&os),
    d_mode(mode)
{}

inline void MultiStreambuf::stream::setMode(Mode mode)
{
    d_mode = mode;
}

inline MultiStreambuf::Mode MultiStreambuf::stream::mode() const
{
    return d_mode;
}

inline std::ostream &MultiStreambuf::stream::ostream()
{
    return *d_os;
}

inline void MultiStreambuf::stream::setOnce(stream &os)
{
    if (os.d_mode == RESET)
        os.d_mode = ONCE;
}

inline MultiStreambuf::MultiStreambuf(std::ostream &os, Mode mode)
{
    insert(os, mode);
}

inline MultiStreambuf::MultiStreambuf(std::vector<stream> const &osvector)
{
    insert(osvector);
}

inline void MultiStreambuf::insert(std::ostream &os, Mode mode)
{
    d_os.push_back(stream(os, mode));
}

inline void MultiStreambuf::insert(std::vector<stream> const &os)
{
    d_os.insert(d_os.end(), os.begin(), os.end());
}

inline MultiStreambuf::iterator MultiStreambuf::begin()
{
    return d_os.begin();
}

inline MultiStreambuf::iterator MultiStreambuf::end()
{
    return d_os.end();
}

inline MultiStreambuf::const_iterator MultiStreambuf::begin() const
{
    return d_os.begin();
}

inline MultiStreambuf::const_iterator MultiStreambuf::end() const
{
    return d_os.end();
}

} // namespace FBB
        
#endif
-------------------------------------------------------


You won't see the implementations of the private virtual members here, as they
are provided in the following header file, which is included by
MultiStreambuf's sources:

-------------------------------------------------------
#include "multistreambuf"

#include <algorithm>
#include <bobcat/fnwrap>

using namespace FBB;

inline std::streamsize MultiStreambuf::xsputn(char const *buffer, 
                                              std::streamsize n)
{
    d_buffer.append(buffer, n);
    return n;
}

inline int MultiStreambuf::sync()
{
    return pSync();
}

inline int MultiStreambuf::overflow(int c)
{
    if (c == EOF)
        pSync();
    else 
        d_buffer += c;

    return c;
}
-------------------------------------------------------


Since it looks like armel's compiler skips the inline definitions of virtual
members when compiling for a shared library, we're in the process of removing
all inline definitions of virtual members, replacing them by non-inline
definitions in separate source files. From tests done so far by George Danchev
we get the impression that this might very well solve (or bypass?) the issue.

If the above is not what you wanted me to send you, please let me know.

Cheers,

-- 
    Frank B. Brokken
    Center for Information Technology, University of Groningen
    (+31) 50 363 9281 
    Public PGP key: http://pgp.surfnet.nl
    Key Fingerprint: DF32 13DE B156 7732 E65E  3B4D 7DB2 A8BE EAE4 D8AA

Attachment: signature.asc
Description: Digital signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]