首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Cereal序列化Lambda函数

用Cereal序列化Lambda函数
EN

Stack Overflow用户
提问于 2019-07-18 13:36:55
回答 3查看 403关注 0票数 3

我想序列化一个函数,并将它发送到运行相同代码的不同进程(动态库)。我最初的方法是使用库谷物和std::function,但这种类型不受支持,有很多原因。

现在,我考虑使用lambda转换为函数指针的方法,但我不太确定我对它们的行为的理解是否正确。使用下面的代码,函数指针指向什么?如果它是一个静态函数,我假设我可以安全地将指针移动到另一个进程,并从那里调用它。

代码语言:javascript
复制
#include <iostream>

// Nice name for function type
using Foo = int(*)();

int main()
{

    auto func = []() -> int
    {
        return 1;
    };

    // convert lambda to function pointer w/o captures
    Foo fo = func;


    // move (serialized) 'Foo fo' to different process
    // ... 


    // calling function pointer in different process
    std::cout << fo();

}

这安全吗?如果没有,我怎样才能达到同样的目标呢?我可以回到原来的静态函数,跳过lambda,但是我喜欢lambda的组织,即lambda带给我的用例。

更新

当我使用模板添加函数作为模板参数,然后序列化类型时,可能会发生什么情况。

代码语言:javascript
复制
#include <iostream>

template<void(*F)()>
class SerializableObj
{
    public:
    void execute() 
    {
        F();
    }
};

void foo() 
{
    std::cout << "HI!";
}

int main()
{
    // calling function pointer in different process
    SerializableObj<foo> obj;

    // serialize and move obj
    // ...

    // in other thread / process
    obj.execute();
}

在戈德波特中,execute()现在通过符号而不是通过函数地址调用函数。(据我所知)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-07-18 13:54:27

一个进程地址空间中指针的二进制值是另一个进程地址空间中的随机位。

动态库通常按字面上的随机地址(称为地址空间随机化)加载,即使不是,它们也被加载到动态地址(这可能碰巧是相同的地址,直到它们没有被加载,因为首先加载了另一个库)。

静态函数并不比lambdas更好。

您需要一个明确的函数表,确保两个进程的顺序相同,并将一个索引传递到该表中。

票数 3
EN

Stack Overflow用户

发布于 2019-07-18 13:59:55

正如其他答案所述,将std::function序列化为二进制代码以序列化任意函数是非常危险的选择。

如果您想通过网络向另一个应用程序实例发送一些函数,我建议您不要通过lambda或std::function来表示函数,而是使用某种语法树。这个表示可以在一边序列化,另一边反序列化,然后执行。

票数 0
EN

Stack Overflow用户

发布于 2019-07-22 22:58:40

您最好创建可调用的对象并序列化它们:

代码语言:javascript
复制
struct Callable {
   virtual void execute() = 0;
};

class MyCallable : public Callable {
public:
   void execute() override { std::cout << "HI! my data is " << x << std::end; }

   // Some data to send along with your Callable
   int x;

   // Cereal serialization function.
   template <class Archive>
   void serialize( Archive & ar )
   {
      ar( x );
   }
};

// Register your Callable type.
CEREAL_REGISTER_TYPE(MyCallable);

您可能不需要这种多态性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57095837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档