How to Attach Streams to Memory/Buffers

Started by
12 comments, last by GenuineXP 15 years, 9 months ago
I found my other post, it was in the other browser instance, lol.

requirement 6: "Serialization of STL containers and other commonly used templates."

Because I was curious I looked in the source for you, it seems to basically resolve into a foreach item in container: archive << item. Its a nonintrustive serializing function which means its using the public (well-defined) interface to serialize a collection's items. I think you're fine serializing to and from different STL implementations using their default support.

If doesn't work for some reason you can just define your own non-intrusive serializer, something like
template<class Archive>void serialize(Archive & ar, std::list<int> & list, const unsigned int version){BOOST_FOREACH(int item, list){ar & item;}}


Quote:I'm also not sure which object should be serialized (some objects are easy to convert to pure C)

If its easy to convert the object to pure C and reconstruct, it will be trivial to write a serialize() method which does it transparently.
Quote:or if there's an elegant way to provide some sort of parameter framework (so that all of my parameters don't just end up being void pointers).

As much as I hate param structs in lieu of function binders I don't see a way around them here. If you are worried about the structs being laid out identically from different compilers, serialize those too.

void dll_fn(void* serialized_params, long size){    ParamStruct params = UnpackParams(serialized_params, size);    std::cout << params.arg1 << params.arg2;}ParamStruct UnpackParams(void* serialized_params, long size){    std::string serialized_params_str(serialized_params, serialized_params+size);    std::stringstream inbuffer(std::stringstream::in);    inbuffer.str(serialized_params_str);    boost::archive::text_iarchive inarchive(inbuffer);    ParamStruct params;    inarchive >> params;    return params;}struct UnpackParams{    int arg1;     std::string arg2;    friend class boost::serialization::access;private:    template<class Archive> void serialize(Archive& ar, const unsigned int version)    {        ar & arg1;        ar & arg2;    }};


I'm sure a better programmer than me can make that code not suck. As you can see I just did some stuff with b::s so its still fresh :)
Advertisement
Quote:Original post by thedustbustr

Quote:Using serialization for the purpose of DLLs is horribly inefficient, and will result in more issues that it would solve. While the most trivial issues are indeed solved, the process is horribly slow (compared to what function call costs).

At risk of sounding like I'm flaming you, I believe that exactly the problem that OP is looking to solve is turned trivial, with so little effort that if performance becomes relevant you can fix it next iteration and discard one day's work.


Let's say we need compression routine, but since we may need to change the compressor, we want to put it in DLL.

Conventional interface:
int compress(void *src, int slen, void *dst, int dlen);

Serialized version:
std::vector<char> compress(std::vector<char> buf);

DLLs are convenient because they allow you to use same memory. Imagine using the above approach to compress megabytes of data, requiring just absurd overhead.

The "slow" here isn't about micro-benchmarking, but simply about using an incredibly unwieldy mechanism in an environment which is designed to avoid just that.

Serialization is applied in the very environments which cannot share memory. DLLs exist for this very purpose. But passing everything by value where you can share memory freely is just unwieldy design.


And if you want true interfaces, there's plenty of other solutions which do that, such as COM, CORBA (shudder), or better yet, languages which support them natively (C# or Java).

C++ is crappy when it comes to this type of interoperability - using C# would be *much* better way, and would work better (less memory overhead, less call overhead, better tools, compile-time checks, .......).

C++ is just the wrong tool for this. It can be done obviously, but it's simply re-inventing the topic in an inefficient way.
For the time being, I'm going to avoid serialization. I'm able to write plugins at this point in C++ but have them communicate across binaries using a purely C interface using a clever trick I've been reading about online and a Dr. Dobb's article. C isn't perfect for this either (e.g., padding structs, etc.), but it's certainly much better than C++. It should do the trick.

I've seen programs written in C/C++ that have used neat plugin systems, so even if it's a bit fragile, I'm sure it can work.

Thanks for the ideas and insight. Java or C# would've made this aspect of the engine seamless and easy (in fact, I've used a trivial plugin architecture in C# before... and it was easy). But this is C++. :-)

Any more ideas/discussion would be great, as I'm still brainstorming a lot about this. For one thing, I'm worried I can't really justify this whole plugin system very well in the first place. Does anyone know any examples of plugin-powered engines and how they leverage them?
What about serializing exceptions (and only exceptions)? I want to add a stack-like set of hooks in plugins (using a purely C interface) so that exceptions can be propagated and rethrown in client applications. This is a little tough, because there are actually two layers of dynamics to get through: the engine is a shared library, and the plugins it loads are also shared libraries (typically loaded at runtime).

Since this is a very special case, I think serialization would be reasonable here. I can't just pass the exceptions around as (C++) objects, because I'm using a C interface. An opaque pointer to memory, however, should work.

It may be very slow... but exceptions occur in exceptional cases anyway. I'll just have to be very strict about where I allow them to be thrown.

Any thoughts?

This topic is closed to new replies.

Advertisement