Click here to Skip to main content
14,922,447 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, Can anyone please help me in how to serialize/deserialize structure with function pointer.
I have declared function pointer type like this:
typedef double(*myFunction)(double arg);
End then I want to serialize/deserialize structure that contains initialized myFunction type variable.
Posted

Serialization of different object types in C++ is done with registries. The registry is usually a map in which the key is something that represents the object in the serialized form (for example the name of the type of the object) and the value is something that can reconstruct the object, or the object itself if we are speaking about a constant. In case of a function pointer we are speaking about a constant that can change between 2 separate program startups (in case of relocation) but it doesn't change during between a single startup-termination pair. In case of function pointer registry you use a unique id as the key in the map (like name(string) or an integer id) and as a value you can use either a (void*) if the registry contains function pointers with different signatures or a typed function pointer if the registry contains only function pointers of the same type.

Simple stupid example (VSC++2010) that serializes registered function pointers as their integer IDs:
C++
std::map<int,void*> g_IdToFuncPtr;
std::map<void*,int> g_FuncPtrToId;

template <typename FuncPtrType>
void RegisterFunc(FuncPtrType func)
{
    // check for duplicate registration
    assert(g_FuncPtrToId.find(func) == g_FuncPtrToId.end());
    int id = (int)g_IdToFuncPtr.size();
    g_IdToFuncPtr[id] = func;
    g_FuncPtrToId[func] = id;
}

template <typename FuncPtrType>
size_t Serialize(FuncPtrType func_ptr, void*& buf, const void* buf_end)
{
    if ((const char*)buf_end-(const char*)buf < sizeof(int))
        return 0;
    auto it = g_FuncPtrToId.find(func_ptr);
    assert(it != g_FuncPtrToId.end());
    if (it == g_FuncPtrToId.end())
        return 0;
    *(int*)buf = it->second;
    buf = (char*)buf + sizeof(int);
    return sizeof(int);
}

template <typename FuncPtrType>
size_t Deserialize(FuncPtrType& func_ptr, const void*& buf, const void* buf_end)
{
    if ((const char*)buf_end-(const char*)buf < sizeof(int))
        return 0;
    int id = *(int*)buf;
    auto it = g_IdToFuncPtr.find(id);
    if (it == g_IdToFuncPtr.end())
        return 0;
    func_ptr = (FuncPtrType)it->second;
    buf = (const char*)buf + sizeof(int);
    return sizeof(int);
}

void func1(int param)
{
}

void func2(int param)
{
}

void TestFuncSer()
{
    // filling registry
    RegisterFunc(func1);
    RegisterFunc(func2);

    typedef void (*TFuncType)(int);
    TFuncType func_ptr_variable = func1;
    TFuncType func_ptr_variable2 = func2;

    // serializing
    char buf[0x40];
    const void* buf_end = (buf + sizeof(buf));

    void* q = buf;
    size_t serialized_size = Serialize(func_ptr_variable, q, buf_end);
    size_t serialized_size2 = Serialize(func_ptr_variable2, q, buf_end);

    // deserializing
    const void* p = buf;
    TFuncType deserialized_func_ptr;
    TFuncType deserialized_func_ptr2;
    size_t deserialized_size = Deserialize(deserialized_func_ptr, p, q);
    size_t deserialized_size2 = Deserialize(deserialized_func_ptr2, p, q);
    printf("Done.\n");
}
   
v3
Comments
   
Good points, a 5.
—SA
xenotron 5-Aug-13 15:10pm
   
Thank you!
If the function pointers are used in the C++ program with other purpose than cooperation with plain C code then something is wrong...
H.Brydon 5-Aug-13 15:26pm
   
This isn't really serialization. You are storing function pointers in a lookup table (okay a map) that are all used within one invocation of a program/executable. Serialization in the classic sense means storing something persistently while a program is running, terminating the program and recovering the data with a subsequent instance of the same or another program. It makes no sense to store pointer values across execution contexts (or in some cases, even threads).

You are using a strained sense of "serialization" and I don't think answering OP's question.

[update]
Looking at the wikipedia definition of serialization at http://en.wikipedia.org/wiki/Serialization , it strengthens my point. It says:
Serialization provides:

- a method of persisting objects, for example writing their properties to a file on disk, or saving them to a database.
- a method of remote procedure calls, e.g., as in SOAP.
- a method for distributing objects, especially in software componentry such as COM, CORBA, etc.
- a method for detecting changes in time-varying data.

Your code example is interesting but does none of these things. It is not serialization.

I said (above) that it "means storing something persistently ... (for a) subsequent instance of the same or another program" which is true, but it also includes marshalling across the network, to other systems, to other system types (and other things).

I like your example (I might use it somewhere myself :-) ... but it does not marshall the function pointer data outside the current program's address space and despite the names you are using, it is not serializing or deserializing anything.
xenotron 5-Aug-13 15:42pm
   
Well, then what do you call it? :-) I'm afraid you confuse serialization with its use cases.

Quoting the first few lines of the wiki page: "serialization is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer, or transmitted across a network connection link) and resurrected later in the same or another computer environment."
My example is just a small part of a serialization framework, serialization of one specific type. The list you mentioned in your comment is a list of use cases of serialization frameworks. If you serialize function pointers with my serializer method then you can save them to database, send them as a soap message or corba message and then on the other side you can reconstruct the function pointers.
H.Brydon 5-Aug-13 18:20pm
   
What do I call it (I assume you are asking what serialization is)?

Serialization is the complete act of taking something (data, class, ...) and breaking down all of the pieces and sending somewhere. Generally in the context of applications, it is writing data for an app out to disk and deserialization is the converse, namely reading a data file into memory and building the resulting data structures. In my experience, the concept involves disassembling the pieces and doing some kind of I/O with them. The name "serialization" came from the idea of taking an object (including POD) and streaming it elsewhere through a serial line.

A synonym for serialization is "data marshalling", which is used more frequently in COM and network apps.

All of these serialization examples involve I/O, and logically moving the object/data from memory to "somewhere else". Mapping one piece of data to another place in memory is not serialization.
xenotron 5-Aug-13 19:32pm
   
What you describe here are complex processes and serialization is just a building block of these. Serialization is also something that is built up from smaller and larger blocks. A codepiece that is able to serialze a bool, other snippets to serialize char, short, int, float,... and if the framework supports it then pointers, maybe function pointers (although I never needed this, especially because I never use funcptrs in a C++ program if it isn't needed). When I think of serialization I always think about it as mapping a single or a few objects into a piece of data and the reverse of this as deserialization. All the rest is higher level stuff built on top of these - like networking, and rpc/rmi on top of the network and serialization libraries - but often they are not separated well and melted togeter. In a nice system they are well decoupled and each part can be plugged out and replaced by another implementation.

What I know about marshalling that it is not exactly the synonym of serialization. While serialization deals basically with object<->data conversion, marshaling knows some extra features that aren't really part of serialization and rpc/rmi related (for example object references that reference objects residing on the other side of the channel). I think of marshaling as an extension of serialization or maybe as a separate thing that heavily makes use of serialization (for example to pass method call parameters by value over the channel). Even in case of marshaling, if done well the communication channel can be an interface and not only a socket stream (that is often burned into the implementation without the chance to customize it).
xenotron 5-Aug-13 19:39pm
   
Well, just searched for serialization vs marshalling: some use it as synonyms while some others don't. I heard about it first when I worked with java+corba and those documents differentiated the two. :-)
H.Brydon 5-Aug-13 16:00pm
   
I see that OP flagged your solution as the answer.

+5 from me.
xenotron 5-Aug-13 16:10pm
   
Thank you! :-)
BTW, the wording of the wiki page is a bit confusing: "Serialization provides: - a method of/for ....". I think this misleads people. Serialization is just a low level "object/object_network to data" and "data to object/object_network" converter library that can be used by those higher level libraries (code that saves/loads to/from disk, corba, rpc, network libs, database libs, ...). Serialization alone just converts the state of some objects into a pure (often self-contained) piece of data (like binary, xml, json, whatever), deserialization does the reverse: uses the data to recreate the objects from the data (sometimes with the pointers between them in case of smart frameworks). Its not the role of a serialization library to provide soap, disk saving facility, ...
H.Brydon 5-Aug-13 18:23pm
   
Do you have a reference for that? Every instance of serialization I am familiar with involves and includes I/O.
xenotron 5-Aug-13 19:19pm
   
I know what you mean, people often say serialization even if all they do is just writing out their config file and reading it back without any kind of framework. I'm also using phrase "serializing data into file" but I think the "into file" part is just some additional info. I'm not sure that writing out the file itself and reading back the file is part of what we call serialization in this case. A serialization framework can be very robust and nice piece of master-work even if it provides only a stream interface for data-input and data-output by leaving it for the framework user to provide some implementations (like file stream, socket stream, membuf stream,...). Would you say that in this case the framework is not a serialization framework? I usually draw the line between the serialization engine and the streaming libraries. Maybe others don't... :-)
[no name] 5-Aug-13 20:43pm
   
The best answers often contain examples and this one is excellent.
xenotron 6-Aug-13 4:13am
   
Thank you!
You can't serialize/deserialize pointers of any kind ... pointers to classes, POD, void, functions, code or anything else. Since the address of something can differ between different runs of your program, it doesn't make sense to save a pointer value to file storage.

For the case of function pointers, you probably want to come up with some sort of enumeration of the function(s) you want mapped and store that information. When reading back, use the same table to map the enumeration back to the function pointer.
   
Comments
   
Basically you are right about function pointers, not not about "pointers of any kind". Look, for example, for boost serialization... or .NET serialization (conceptually, in this context, CLI references are managed pointers, equivalent in this respect).
—SA
xenotron 5-Aug-13 14:41pm
   
Why? A function pointer is just a constant. It can easily be handled with a simple registry (map) even if the value of this constant my change between program startups.
   
I'm not talking about a function pointer, Harvey did. But you are right. It actually depends on the purpose of this pointer.
—SA
xenotron 5-Aug-13 14:51pm
   
I wasn't careful when reading this answer anyway, the answer about enumeration/funcptr stuff is okay. :-)
H.Brydon 5-Aug-13 15:59pm
   
Actually OP did (the way I read the question)... but see my replies to pasztorpisti.

In any case, OP flagged his solution as the answer. I'll give +5 to his solution.
H.Brydon 5-Aug-13 15:21pm
   
I think there is a semantic error happening here. Note that I said "it doesn't make sense to save a pointer value to file storage" which is what I think OP was asking. If you are serializing data, it makes no sense whatsoever to store the pointer value (ever). It does make sense to dereference the pointer and store the data that is found there (recursively if that data contains pointers).

A function pointer in system space might have some more stability than a function pointer to your own code, but not a pointer to a function in your own code.

Really, I would not consider persisting an address of any type to file storage. That sounds like a place where angels would fear to tread...
   
I did not mean literally storing the pointer. The pointed object is serialized. As the object graph can have circular references, the pointers should be collected during serialization, so all referenced objects should be serialized only once and execution not going in infinite cycle. This is how appropriate techniques work. After all, look what .NET FCL Data Contract does...
—SA
xenotron 5-Aug-13 19:47pm
   
Serialization of a few objects with pointers between them is quite common. Pointer serialization, or in other words: the serialization of references between objects is very similar to graph duplication. You can easily do it with a map. You generate a unique id for every pointer value during serialization, the id must be unique only in the context of serialized data. Create an initially empty map that maps pointer values to unique ids. Walk the object graph (by handling cycles) and whenever you encounter a pointer you serialize it this way: Search for the pointer in the map, if the map contains it then serialize the pointer as the unique id found in the map, otherwise generate a new unique id and put the pointer to the map. Of course the unique ids must be saved with the objects they identify as well. Of course after deserialization the pointer values will be different and you can deserialize the objects more than once if their fields do not contain anything that shouldn't exist in multiple instances in your system.
H.Brydon 5-Aug-13 22:28pm
   
Sorry for being distracted; dealing with an air conditioning problem and associated repair guy.

This turned out to have far more discussion than I anticipated or intended. Thanks for your insights and observations. I think we beat it to death.
xenotron 6-Aug-13 4:14am
   
:-) :-) :-)
pasztorpisti, thanks for your explanation and simple example code)
   
Comments
xenotron 5-Aug-13 15:56pm
   
You are welcome!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900