V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Huelse
V2EX  ›  C++

请问这样的 C++函数如何用 pybind11 绑定?

  •  
  •   Huelse · 2019-07-15 10:12:46 +08:00 · 3580 次点击
    这是一个创建于 1744 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想将以下类中的方法通过 pybind11 绑定到 python 中使用,但无奈看了好一会儿官方文档没有找到合适的例子(可能我眼瞎),所以来 V2 请求各位支招

    class SEALContext
    {
    	...
        static auto Create(const EncryptionParameters &parms,
            bool expand_mod_chain = true,
            sec_level_type sec_level = sec_level_type::tc128)
    	{
         	return std::shared_ptr<SEALContext>(
    		new SEALContext(
    			parms,
    			expand_mod_chain,
    			sec_level,
    			MemoryManager::GetPool())
    		);
    	}
        ...
    }
    

    绑定 wrapper.cpp 中我是这么写的能编译通过:

    PYBIND11_MODULE(seal, m) {
    	py::class_<SEALContext>(m, "SEALContext")
    		.def("Create", &SEALContext::Create)
    }
    

    我想在 Python 中 SEALContext.Create(parms)这样调用,经测试,Python 总是提示我需要传入三个参数,但我只想传入 parms 这一个,如果我在 wrapper.cpp 中限定,就编译不通过,然后不知道该怎么做了。。。 感谢各位了!

    18 条回复    2019-07-22 12:38:04 +08:00
    wutiantong
        1
    wutiantong  
       2019-07-15 10:20:23 +08:00   ❤️ 1
    直接用 lambda 定义好了。
    wutiantong
        2
    wutiantong  
       2019-07-15 10:22:04 +08:00   ❤️ 1
    .def("Create", [] (const EncryptionParameters &parms) { return SEALContext::Create(parms); } )

    就像这个样子。
    Huelse
        3
    Huelse  
    OP
       2019-07-15 11:22:31 +08:00
    @wutiantong #2 哇,我还在想这个咋用,感谢!~
    Huelse
        4
    Huelse  
    OP
       2019-07-15 20:16:43 +08:00
    @wutiantong 呃,遇到了个新问题,请问你知道
    ```
    double free or corruption (out)
    Aborted (core dumped)
    ```
    错误怎么处理吗?
    https://github.com/pybind/pybind11/issues/1839
    我按照这个,弄不好呀
    wutiantong
        5
    wutiantong  
       2019-07-16 00:20:17 +08:00   ❤️ 1
    @Huelse double free 广泛存在于 C++程序中,本质上就是对动态申请的内存两次执行 free(),这类问题在很多场景下都可能出现,所以在不清楚你的代码的情况下我是帮不到你的。
    wutiantong
        6
    wutiantong  
       2019-07-16 00:21:18 +08:00   ❤️ 1
    至少你需要定位到程序挂掉的那个位置。
    Huelse
        7
    Huelse  
    OP
       2019-07-16 08:23:37 +08:00
    @wutiantong #5 好的,这个是微软 SEAL 库的源码,我首先想的是我 pybind11 里写的有问题
    wutiantong
        8
    wutiantong  
       2019-07-16 09:38:18 +08:00   ❤️ 1
    @Huelse 我看到那个 issue 原来就是你提的,看到了代码后我发现问题应该是在于:
    key_context_data() 这个方法的返回值类型是 std::shared_ptr<ContextData>,然而你的 binding 并没有做任何 wrapping 处理,并且在 test.py 里直接把它当作 ContextData 来调用了( context.key_context_data().parms() 这行 )
    Huelse
        9
    Huelse  
    OP
       2019-07-16 10:46:44 +08:00
    @wutiantong #8 是的,原谅我第一次接触,我还在想怎么弄😂
    Huelse
        10
    Huelse  
    OP
       2019-07-16 15:41:00 +08:00
    @wutiantong #8
    pybind11 文档给我的方案有两个,但都好像是要改 c++代码的,我不希望这样。
    https://pybind11.readthedocs.io/en/master/advanced/smart_ptrs.html#std-shared-ptr

    ```
    inline auto key_context_data() const
    {
    auto data = context_data_map_.find(key_parms_id_);
    return (data != context_data_map_.end()) ?
    data->second : std::shared_ptr<ContextData>{ nullptr };
    }
    ```
    我想问题应该是这里的,请问我该怎么做?
    wutiantong
        11
    wutiantong  
       2019-07-16 15:52:18 +08:00   ❤️ 1
    @Huelse

    看起来只需要把
    // SEALContext::ContextData
    py::class_<SEALContext::ContextData>(m, "SEALContext::ContextData")

    改成
    py::class_<SEALContext::ContextData, std::shared_ptr<SEALContext::ContextData>>(m, "SEALContext::ContextData")

    就行了。
    Huelse
        12
    Huelse  
    OP
       2019-07-16 16:38:31 +08:00
    @wutiantong #11 我透,还真是这样!我该怎么感谢你
    wutiantong
        13
    wutiantong  
       2019-07-16 17:11:47 +08:00
    @Huelse 不用谢~
    Huelse
        14
    Huelse  
    OP
       2019-07-17 22:38:09 +08:00
    @wutiantong #13
    尴尬。。这次遇到了`Segmentation fault (core dumped)` 段错误
    又弄不好了
    python 里是这样的
    ```
    evaluator = Evaluator(context)
    ...
    x_encrypted = Ciphertext()
    ...
    x_sq_plus_one = Ciphertext()
    evaluator.square(x_encrypted, x_sq_plus_one)
    ```
    wrapper.cpp 中是
    ```
    py::class_<Evaluator>(m, "Evaluator")
    .def("square", (void (Evaluator::*)(const Ciphertext &, Ciphertext &)) &Evaluator::square)
    ```
    怎么调试都是`Segmentation fault (core dumped)`
    能提供一些意见吗?
    https://github.com/Huelse/pyseal/blob/master/pyseal/wrapper.cpp
    谢谢!
    wutiantong
        15
    wutiantong  
       2019-07-18 10:59:30 +08:00   ❤️ 1
    @Huelse

    x_encrypted = Ciphertext(context)
    x_sq_plus_one = Ciphertext(context)

    改成这样试试。
    Huelse
        16
    Huelse  
    OP
       2019-07-18 15:14:46 +08:00
    @wutiantong
    经测试还是不行的,
    好在我发现了是 MemoryPoolHandle()的问题,只需要

    pool = MemoryPoolHandle().New(False)
    evaluator.square(x_encrypted, x_sq_plus_one, pool)

    就可以了,不过还是谢谢您~
    Huelse
        17
    Huelse  
    OP
       2019-07-22 12:24:12 +08:00
    @wutiantong #15
    啊,再打扰下,这种 template 该怎么绑定呢?

    我已包含#include <pybind11/complex.h>
    ```
    template<typename T,
    typename = std::enable_if_t<std::is_same<T, double>::value ||
    std::is_same<T, std::complex<double>>::value>>
    inline void decode(const Plaintext &plain, std::vector<T> &destination,
    MemoryPoolHandle pool = MemoryManager::GetPool())
    {
    ...
    }
    ```

    虽然我把 T 替换成 double 类型可以编译成功,但使用中,函数并不能对这个 vector 做出修改
    ``` error
    .def("decode", (void (CKKSEncoder::*)(const Plaintext &, std::vector<double> &, MemoryPoolHandle)) &CKKSEncoder::decode)
    ```
    谢谢!
    wutiantong
        18
    wutiantong  
       2019-07-22 12:38:04 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1027 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 19:25 · PVG 03:25 · LAX 12:25 · JFK 15:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.