简体   繁体   中英

boost serialization of opaque types

I want to be able to serialize a Windows HANDLE:

typedef void *HANDLE

If I try to compile using following:

struct Foo
{
    HANDLE file;

protected:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/)
    {
        ar & file;
    }
};

I get compile errors:

c:\projects\3rdparty\src\boost\include\boost/mpl/print.hpp(51) : warning C4308: negative integral constant converted to unsigned type
        c:\projects\3rdparty\src\boost\include\boost/serialization/static_warning.hpp(92) : see reference to class template instantiation 'boost::mpl::print<T>' being compiled
        with
        [
            T=boost::serialization::BOOST_SERIALIZATION_STATIC_WARNING_LINE<98>
        ]
        c:\projects\3rdparty\src\boost\include\boost/archive/detail/check.hpp(98) : see reference to class template instantiation 'boost::serialization::static_warning_test<B,L>' being compiled
        with
        [
            B=false,
            L=98
        ]
        c:\projects\3rdparty\src\boost\include\boost/archive/detail/oserializer.hpp(313) : see reference to
function template instantiation 'void boost::archive::detail::check_object_tracking<T>(void)' being compiled
        with
        [
            T=Foo
        ]
        c:\projects\3rdparty\src\boost\include\boost/archive/detail/oserializer.hpp(525) : see reference to
function template instantiation 'void boost::archive::detail::save_non_pointer_type<Archive>::invoke<T>(Archive &,T &)' being compiled
        with
        [
            Archive=boost::archive::text_oarchive,
            T=Foo
        ]

But if I change file to an int , everything is fine. How do I tell boost to serialize HANDLEs as ints?

Thanks

HANDLE is a Windows-API-specific data type defined in winnt.h . According to the MSDN ,

A handle to an object. This type is declared in WinNT.h as follows:

 typedef PVOID HANDLE; 

So, now we see that HANDLE is really just void * -- representing a handle to an object. Think about what it is that you're trying to do; does it make sense to serialize a pointer to some object in the Windows API?

Instead, try to serialize what it takes to retrieve an equivalent HANDLE ; judging by the name of the member, I'm going to guess you used CreateFile -- so, you'll need to know...

  • The file name
  • The desired access (eg GENERIC_READ | GENERIC_WRITE )
  • The share mode (eg FILE_SHARE_DELETE )
  • Optionally, the security attributes
  • The creation disposition (ie CREATE_NEW , TRUNCATE_EXISTING , etc.)
  • The file or device flags and attributes
  • Optionally, a template file -- for copying its attributes when creating a file

Now, if you really don't want to be doing that -- you're positive you want the pointer value -- maybe try serializing it after casting via reinterpret_cast to std::intptr_t or std::uintptr_t (as might be defined in cstdint as of C++11).

ar & reinterpret_cast<std::intptr_t>(file);

... then you should couple this with something as follows (when deserializing):

std::intptr_t _file;
ar & _file;
HANDLE file = std::reinterpret_cast<HANDLE>(_file);

Ended up solving the problem by splitting the serialization. Seems like a hack though:

struct Foo
{
    HANDLE file;

protected:
    friend class boost::serialization::access;

    template<class Archive>
    void save(Archive & ar, const unsigned int /*version*/) const
    {
        unsigned int _file = reinterpret_cast<unsigned int>(file);
        ar & _file;
    }

    template<class Archive>
    void load(Archive & ar, const unsigned int /*version*/)
    {
        unsigned int _file;
        ar & _file;
        file = reinterpret_cast<HANDLE>(_file);
    }
    BOOST_SERIALIZATION_SPLIT_MEMBER()
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM