0

I am a newbie to cereal and lately I ran into an odd issue, I have my serialization code inside an external DLL, in the code I use cereal's polymorphism functionality, when trying to invoke the archive() method that is in the DLL from the executable, the program crashes, this however only happens if the archive() method is called from compiled code (I suspect), if it is visible to the caller (called directly by the main function) there is no crash, also if I disable the polymorphic usage there is no crash, also if I change the DLL to be a Static lib there is no crash.

the crash is caused by an UNREGISTERED_POLYMORPHIC_EXCEPTION. it specifies that I need to register the polymorphic type and it seems to not be present in the binding map although I register it in advance.

I devised a small example to demonstrate the issue: I am using Windows 10 MSVC 2022 cereal v1.3.2

In External DLL

Archiver.hpp

#pragma once

#include <cereal/archives/xml.hpp>
#include <cereal/types/polymorphic.hpp>
#include <cereal/types/vector.hpp>

#include <iostream>
#include <fstream>

#include "myclasses.hpp"

class __declspec(dllexport) Archiver
{
public:
    void add(std::shared_ptr<BaseClass> cls)
    {
        classes.push_back(cls);
    }

    void save()
    {
        std::ofstream os("polymorphism_test.xml");
        cereal::XMLOutputArchive oarchive(os);

        oarchive(classes);
    }

    void load()
    {
        {
            std::ifstream is("polymorphism_test.xml");
            cereal::XMLInputArchive iarchive(is);

            std::vector<std::shared_ptr<BaseClass>> ptrs;
            iarchive(ptrs);

            //ptrs[0]->sayType();  
            ptrs[0]->sayType();
        }
    }
    

    std::vector<std::shared_ptr<BaseClass>> classes;
};

IndirectCaller.hpp

#pragma once

struct BaseClass;

#include <memory>

class __declspec(dllexport) indirectCaller
{
public:
    void call(std::shared_ptr<BaseClass> cls);
};

IndirectCaller.cpp

#include "indirectCaller.hpp"

#include "archiver.hpp"

void indirectCaller::call(std::shared_ptr<BaseClass> cls)
{
    Archiver a;
    a.add(cls);
    a.save();
    a.load();
}

myclasses.hpp

#pragma once

// Include the polymorphic serialization and registration mechanisms
#include <cereal/types/polymorphic.hpp>

 // A pure virtual base class
struct BaseClass
{
    virtual void sayType() = 0;
};

In Executable

NewDerived.hpp

#pragma once

// Include the polymorphic serialization and registration mechanisms
#include <cereal/types/polymorphic.hpp>

#include "myclasses.hpp"

// A class derived from BaseClass
struct DerivedClassThree : public BaseClass
{
    void sayType()
    {
        std::cout << "Derived 3" << std::endl;
    }

    int x;

    template<class Archive>
    void serialize(Archive& ar)
    {
        ar(x);
    }
};
#include <cereal/archives/binary.hpp>
#include <cereal/archives/xml.hpp>
#include <cereal/archives/json.hpp>

CEREAL_REGISTER_TYPE(DerivedClassThree);
CEREAL_REGISTER_POLYMORPHIC_RELATION(BaseClass, DerivedClassThree)

main.cpp


#include "myclasses.hpp"

#include <cereal/archives/xml.hpp>
#include <cereal/types/polymorphic.hpp>

#include <iostream>
#include <fstream>

#include "newderived.hpp"

#include "indirectCaller.hpp"

int main()
{
    indirectCaller a;
    a.call(std::make_shared<DerivedClassThree>());

    return 0;
}

0

Browse other questions tagged or ask your own question.