sha*_*aki 14 c++ serialization closures function-object c++11
是否可以std::function
在C++中序列化和反序列化a ,函数对象或闭包?怎么样?C++ 11是否有助于此?是否有任何图书馆支持可用于此类任务(例如,在Boost中)?
例如,假设一个C++程序std::function
需要与另一台机器上的另一个C++程序进行通信(比如通过TCP/IP套接字).在这种情况下你有什么建议?
为了澄清,要移动的功能应该是纯粹的,没有副作用的.所以我没有安全性或状态不匹配问题.
该问题的解决方案是构建一个小的嵌入式域特定语言并序列化其抽象语法树.我希望我能找到一些语言/库支持来代替移动与机器无关的函数表示.
Dan*_*bos 11
是的,用于函数指针和闭包.不适合std::function
.
函数指针是最简单的 - 它只是一个像任何其他指针一样的指针,因此您可以将其作为字节读取:
template <typename _Res, typename... _Args>
std::string serialize(_Res (*fn_ptr)(_Args...)) {
return std::string(reinterpret_cast<const char*>(&fn_ptr), sizeof(fn_ptr));
}
template <typename _Res, typename... _Args>
_Res (*deserialize(std::string str))(_Args...) {
return *reinterpret_cast<_Res (**)(_Args...)>(const_cast<char*>(str.c_str()));
}
Run Code Online (Sandbox Code Playgroud)
但我很惊讶地发现,即使没有重新编译,函数的地址也会在程序的每次调用时发生变化.如果要传输地址,则不是很有用.这是由ASLR引起的,你可以在Linux上关闭your_program
它setarch $(uname -m) -LR your_program
.
现在您可以将函数指针发送到运行相同程序的其他计算机,并调用它!(这不涉及传输可执行代码.但除非您在运行时生成可执行代码,否则我认为您不是在寻找它.)
lambda函数是完全不同的.
std::function<int(int)> addN(int N) {
auto f = [=](int x){ return x + N; };
return f;
}
Run Code Online (Sandbox Code Playgroud)
f
将捕获的值int N
.它在内存中的表现方式与int
!编译器为lambda生成一个未命名的类,其中f
一个是实例.这个类已经operator()
超载了我们的代码.
未命名的类提出了序列化的问题.它还提出了从函数返回lambda函数的问题.后一个问题通过解决std::function
.
std::function
据我所知,通过创建一个模板化的包装类来实现,该类通过模板类型参数有效地保存对lambda函数后面的未命名类的引用.(这是_Function_handler
在功能性.)std::function
接受一个函数指针到一个静态方法(_M_invoke
此包装类并存储加上封盖值的).
不幸的是,所有内容都隐藏在private
成员中,并且不存储闭包值的大小.(它不需要,因为lambda函数知道它的大小.)
所以std::function
不适合序列化,但作为蓝图很好.我跟着它做了什么,简化了很多(我只想序列化lambdas,而不是无数其他可调用的东西),保存了闭包值的大小size_t
,并添加了(de)序列化的方法.有用!
没有.
C++没有内置的序列化支持,从来没有考虑过将代码从一个进程传输到另一个进程的想法,以免一台机器到另一台机器.可能这样做的语言通常具有IR(与机器无关的代码的中间表示)和反射.
因此,您只需编写一个用于传输所需操作的协议,并且DSL方法肯定是可行的......取决于您希望执行的各种任务以及性能需求.
另一种解决方案是使用现有语言.例如,Redis NoSQL数据库嵌入了LUA引擎并可以执行LUA脚本,您可以执行相同的操作并在网络上传输LUA脚本.